用Python写一个贪吃蛇
最近在学Python,想做点什么来练练手,命令行的贪吃蛇一般是C的练手项目,但是一时之间找不到别的,就先做个贪吃蛇来练练简单的语法。
由于Python监听键盘很麻烦,没有C语言的kbhit(),所以这条贪吃蛇不会自己动,运行效果如下:
要求:用#表示边框,用*表示食物,o表示蛇的身体,O表示蛇头,使用wsad来移动
Python版本:3.6.1
系统环境:Win10
类:
board:棋盘,也就是游戏区域
snake:贪吃蛇,通过记录身体每个点来记录蛇的状态
game:游戏类
本来还想要个food类的,但是food只需要一个坐标,和一个新建,所以干脆使用list来保存坐标,新建food放在game里面,从逻辑上也没有太大问题
源码
# Write By Guobao
# 2017/4//7
#
# 贪吃蛇
# 用#做边界,*做食物,o做身体和头部
# python 3.6.1 import copy
import random
import os
import msvcrt # the board class, used to put everything
class board: __points =[] def __init__(self):
self.__points.clear()
for i in range(22):
line = []
if i == 0 or i == 21:
for j in range(22):
line.append('#')
else:
line.append('#')
for j in range(20):
line.append(' ')
line.append('#')
self.__points.append(line) def getPoint(self, location):
return self.__points[location[0]][location[1]] def clear(self):
self.__points.clear()
for i in range(22):
line = []
if i == 0 or i == 21:
for j in range(22):
line.append('#')
else:
line.append('#')
for j in range(20):
line.append(' ')
line.append('#')
self.__points.append(line) def put_snake(self, snake_locations):
# clear the board
self.clear() # put the snake points
for x in snake_locations:
self.__points[x[0]][x[1]] = 'o' # the head
x = snake_locations[len(snake_locations) - 1]
self.__points[x[0]][x[1]] = 'O' def put_food(self, food_location):
self.__points[food_location[0]][food_location[1]] = '*' def show(self):
os.system("cls")
for i in range(22):
for j in range(22):
print(self.__points[i][j], end='')
print() # the snake class
class snake:
__points = [] def __init__(self):
for i in range(1, 6):
self.__points.append([1, i]) def getPoints(self):
return self.__points # move to the next position
# give the next head
def move(self, next_head):
self.__points.pop(0)
self.__points.append(next_head) # eat the food
# give the next head
def eat(self, next_head):
self.__points.append(next_head) # calc the next state
# and return the direction
def next_head(self, direction='default'): # need to change the value, so copy it
head = copy.deepcopy(self.__points[len(self.__points) - 1]) # calc the "default" direction
if direction == 'default':
neck = self.__points[len(self.__points) - 2]
if neck[0] > head[0]:
direction = 'up'
elif neck[0] < head[0]:
direction = 'down'
elif neck[1] > head[1]:
direction = 'left'
elif neck[1] < head[1]:
direction = 'right' if direction == 'up':
head[0] = head[0] - 1
elif direction == 'down':
head[0] = head[0] + 1
elif direction == 'left':
head[1] = head[1] - 1
elif direction == 'right':
head[1] = head[1] + 1
return head # the game
class game: board = board()
snake = snake()
food = []
count = 0 def __init__(self):
self.new_food()
self.board.clear()
self.board.put_snake(self.snake.getPoints())
self.board.put_food(self.food) def new_food(self):
while 1:
line = random.randint(1, 20)
column = random.randint(1, 20)
if self.board.getPoint([column, line]) == ' ':
self.food = [column, line]
return def show(self):
self.board.clear()
self.board.put_snake(self.snake.getPoints())
self.board.put_food(self.food)
self.board.show() def run(self):
self.board.show() # the 'w a s d' are the directions
operation_dict = {b'w': 'up', b'W': 'up', b's': 'down', b'S': 'down', b'a': 'left', b'A': 'left', b'd': 'right', b'D': 'right'}
op = msvcrt.getch() while op != b'q':
if op not in operation_dict:
op = msvcrt.getch()
else:
new_head = self.snake.next_head(operation_dict[op]) # get the food
if self.board.getPoint(new_head) == '*':
self.snake.eat(new_head)
self.count = self.count + 1
if self.count >= 15:
self.show()
print("Good Job")
break
else:
self.new_food()
self.show() # 反向一Q日神仙
elif new_head == self.snake.getPoints()[len(self.snake.getPoints()) - 2]:
pass # rush the wall
elif self.board.getPoint(new_head) == '#' or self.board.getPoint(new_head) == 'o':
print('GG')
break # normal move
else:
self.snake.move(new_head)
self.show()
op = msvcrt.getch() game().run()
笔记:
1.Python 没有Switch case语句,可以利用dirt来实现
2.Python的=号是复制,复制引用,深复制需要使用copy的deepcopy()函数来实现
3.即使在成员函数内,也需要使用self来访问成员变量,这和C++、JAVA很不一样
2017.4.11 更新
完成了贪吃蛇之后,我开始打一个简单的学生信息管理系统,内容简单,数据量小,但是可以用上MVC架构,又可以更好的训练。过程中发现自己在贪吃蛇中有一个致命的问题,虽然在贪吃蛇中,这个问题并不会影响结果。
先看board类中的部分代码:
class board: __points =[]
4 # 后面不重要
咋一看没有问题,但是看初始化__point的位置,并不是在__init__()中第一次初始化,这种情况下,__point是一个类变量,而不是一个成员变量,如果__point是一个不可变的类型(如整形),那可能不会看出什么影响,但是当它是一个可变的类型,如list,就会有很大的问题,看我在命令行上的试验:
①整形例子
到此为止,和我一开始的想法没有冲突,请看下面:
惊讶的发现可以直接通过类名来访问到num变量,而且还一直保持着最初的值,还能变
②list例子
试验的时候心理活动:嗯→很正常→就该这样→卧槽???
这时候可以再来一句:
分析:整形例子中,当我修改num的值,其实是让num指向了新的内存,所以会有c1,c2有着各自的num值;
而在list例子中,当我修改cc的值,修改的是cc指向的内存的值,cc一直指向同一个内存
个人理解:不论哪一个例子,都是在复制类变量,所以会有这种现象
贪吃蛇中,因为Snake和board我都只有一个实例,所以没有明显的问题。
与此相关可以看这篇博客:http://www.cnblogs.com/duanv/p/5947525.html
函数的默认参数中也有相似的问题,可以看:http://blog.jobbole.com/42706/#article-comment
用Python写一个贪吃蛇的更多相关文章
- 如何用Python写一个贪吃蛇AI
前言 这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游戏, 估计大部分人都玩过.但如果仅仅是贪吃蛇游戏,那么它就没有什么让人涨姿势的地方了. 问题的关键在于,图片中的贪吃蛇真的很贪吃XD, ...
- 使用Python写一个贪吃蛇
参考代码http://blog.csdn.net/leepwang/article/details/7640880 我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的 ...
- python 写一个贪吃蛇游戏
#!usr/bin/python #-*- coding:utf-8 -*- import random import curses s = curses.initscr() curses.curs_ ...
- 用 Python 写个贪吃蛇,保姆级教程!
本文基于 Windows 环境开发,适合 Python 新手 本文作者:HelloGitHub-Anthony HelloGitHub 推出的<讲解开源项目>系列,本期介绍 Python ...
- 【C/C++】10分钟教你用C++写一个贪吃蛇附带AI功能(附源代码详解和下载)
C++编写贪吃蛇小游戏快速入门 刚学完C++.一时兴起,就花几天时间手动做了个贪吃蛇,后来觉得不过瘾,于是又加入了AI功能.希望大家Enjoy It. 效果图示 AI模式演示 imageimage 整 ...
- pygame试水,写一个贪吃蛇
最近学完python基础知识,就想着做一个游戏玩玩,于是就在https://www.pygame.org/docs/学着做了个贪吃蛇游戏. 首先要导入模块. import pygame import ...
- 一步一步用Canvas写一个贪吃蛇
之前在慕课网看了几集Canvas的视频,一直想着写点东西练练手.感觉贪吃蛇算是比较简单的了,当年大学的时候还写过C语言字符版的,没想到还是遇到了很多问题. 最终效果如下(图太大的话 时间太长 录制gi ...
- Python写的贪吃蛇游戏例子
第一次用Python写这种比较实用且好玩的东西,权当练手吧 游戏说明: * P键控制“暂停/开始”* 方向键控制贪吃蛇的方向 源代码如下: 复制代码代码如下: from Tkinter import ...
- 用js写一个贪吃蛇小游戏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- Protocol Buffers(2):编码与解码
目录 Message Structure 解码代码一窥 varint Protobuf中的整数和浮点数 Length-delimited相关类型 小结 参考 博客:blog.shinelee.me | ...
- Java面试前需要了解的东西
一.前言 只有光头才能变强 回顾前面: 广州三本找Java实习经历 上一篇写了自己面试的经历和一些在面试的时候遇到的题目(笔试题和面试题). 我在面试前针对Java基础也花了不少的时间,期间也将自己写 ...
- 用markdown + html写一封简历
0. 前言 1. 阶段1 - 确定需要几个模块 2. 阶段2 - 使用纯文字填充简历 3. 阶段3 - 预留空格 4. 阶段4 - 文章垂直方向的调整 5. 阶段5 - 居中对齐 6. 阶段6 - 加 ...
- 设计模式之Singleton模式和Strategy模式是什么
Singleton模式 单例模式,也交单子模式,有时候系统只需要拥有一个全局对象. 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方 ...
- gitbook 入门教程之快速体验
本文主要介绍三种使用 gitbook 的方式,分别是 gitbook 命令行工具,Gitbook Editor 官方编辑器和 gitbook.com 官网. 总体来说,三种途径适合各自不同的人群,找到 ...
- PIC单片机基础2
PIC中档系列单片机,每条指令14位,共有35条汇编指令,根据操作对象不同,可将其分为三类: 字节操作类指令 位操作类指令 立即数与控制类操作指令 1.字节操作类指令,以MOVF指令为例: 指令:MO ...
- 最小生成树之Kruskal(克鲁斯卡尔)算法
学习最小生成树算法之前我们先来了解下下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所 ...
- 前端技术大行其道,再不拥抱TypeScript你就老了!
本篇文章旨在介绍下TypeScript这门新兴的程序设计语言,不需要你有多么强的专业知识,只需要你有半支烟的功夫. 好了,废话不多说,赶紧进入正题.为什么你需要拥抱TypeScript?那么你首先需要 ...
- 当 “HTTP” 先生遇上“S”小姐
情人节的晚上,天空中淅淅沥沥的下着带有些寒意的小雨.HTTP 先生孤零零的坐在咖啡厅中,对着面前的电脑发呆.他有意的屏蔽掉了周边情侣们的窃窃私语,这对单身的他来说是狗粮,也是一阵阵伤害.这时,咖啡厅的 ...
- 死磕 java集合之HashSet源码分析
问题 (1)集合(Collection)和集合(Set)有什么区别? (2)HashSet怎么保证添加元素不重复? (3)HashSet是否允许null元素? (4)HashSet是有序的吗? (5) ...