大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
Python命令行小游戏—贪吃蛇
前言
为了初步学习Python更有兴趣,决定做个学编程大多都会做的小游戏—贪吃蛇,因为是刚刚开始学习,不足之处,希望大家多多指正。
一、贪吃蛇游戏初始界面及地图
1.游戏初始界面
def mune():
os.system("color 0a")
dll.set_cmd(0, 2);print("□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□")
dll.set_cmd(0, 3);print("□□□□□■■■■□□□□□□□贪吃蛇□□□□□□□□□■□□□ 操作指南 □□□□")#7
dll.set_cmd(0, 4);print("□□□□■■□□■■□□□□□□□□□□□□□□□□□□■□□□方向键 改变方向□□□□")#5
dll.set_cmd(0, 5);print("□□□■■□□□□□□□□□□2021.05.06□□□□□□□□■□□□ESC 退出游戏□□□□□□")
dll.set_cmd(0, 6);print("□□□□■■□□□□□□□□□□□□□□□□□□□□□□■□□□SPACE 暂停游戏□□□□□□□□□")
dll.set_cmd(0, 7);print("□□□□□■■■■□□□□■■■■□□□□■■■□□□□■□□■■□□□□■■■■■□□")
dll.set_cmd(0, 8);print("□■□□□□□■■■□□■□□□□■□□■□□□■□□□■■□□□□□□■□□□□□■□")
dll.set_cmd(0, 9);print("□□■□□□□□■■■□■□□□□■□■□□□□■□□□■■□□□□□■□□■■■■□□")
dll.set_cmd(0,10);print("□□□■■□□■■■□□■□□□□■□□■□□■□■□□■□■□□□□□■□□□□□□□")
dll.set_cmd(0,11);print("□□□□■■■■□□□□■□□□□■□□□■■□□■■□■□□■■■□□□■■■■■□□")#24
dll.set_cmd(0,12);print("□□□□□□□□□□□□□□□□□□按空格开始游戏□□□□□□□□□□□□□□□□□□□")
这里使用了os库和ctypes库以及调用的.dll自建动态库,第二节会详细说明
2.游戏地图
def wall(x,y):#绘制围墙
i=0;j=0
while i<=x:
print('■',end="")
for j in range(y):
if i==0:
print('■', end="")
elif i==20:
print('■', end="")
else:
print(" ",end="")
j+=1
print('■')
i+=1
j=0
简单的使用Python的输出函数print()做一个围墙,默认情况下函数内的 end=“/n”
二、命令符的设置、输出刷新和按键检测
1.库支持
- os库中的os.system(“命令行指令”) 函数可执行命令行中的指令,具体指令可在命令行中输入help回车获得相关信息
- c语言能够更好的对命令行的输出进行刷新,这里通过调用.dll的方式调用c语言,具体的使用可观看此视频python和C语言混合编程
2.c语言代码
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>
//命令行光标显示(1)隐藏(0)
_declspec(dllexport) void _stdcall init_cmd(int x)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = x; //控制台光标状态,x=1显示,x=0隐藏
SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
}
//命令行光标移动函数
_declspec(dllexport) void _stdcall set_cmd(int x, int y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
//获取键盘输入
_declspec(dllexport) int _stdcall c_getch()
{
int key;
if (_kbhit()) {
//_kbhit()为按键检测,有按键输出1,没有输出0
key = _getch();
Sleep(10);
return key;
}
else;
}
3.Python代码(变量初始化及游戏初始化)
import os,time,ctypes,random
wall_x,wall_y ,eat_flag= 20,21,1
move_up,move_down,move_left,move_right,esc,space = 72,80,75,77,27,32
def init_game():#游戏界面初始化
global getkey, key, snake_x, snake_y, snake_list#全局变量声明
os.system("mode con cols=48 lines=22") # 设置命令符窗口大小
os.system("cls")
os.system("color 2b") # 设置字体和背景颜色
wall(wall_x, wall_y) # 绘制围墙
dll.set_cmd(0, 1)
print("■□□□□○")
snake_list = [[2, 1], [4, 1], [6, 1], [8, 1], [10, 1]]
snake_x, snake_y ,getkey,key= 10, 1,0,0
def init():#命令符及游戏初始化
ctypes.windll.kernel32.SetConsoleTitleW("贪吃蛇") # 修改命令符标题
os.system("mode con cols=88 lines=15") # 设置命令符窗口大小
dll.init_cmd(0) # 设置光标状态
当定义函数内有全局变量的值发生变化时,需要进行全局变量声明
三、蛇的移动
def snake_move(*lis):#蛇移动
dll.set_cmd(snake_list[0][0], snake_list[0][1])
print(" ")
snake_list.append(lis[0])
if eat_flag==0:
snake_list.pop(0)
dll.set_cmd(snake_list[-1][0], snake_list[-1][1])
print("○")
n = 0
for n in range(len(snake_list)-2):
dll.set_cmd(snake_list[-2-n][0], snake_list[-2-n][1])
print("□")
n += 1
def move():#蛇移动防倒走
global snake_x, snake_y
if [snake_x, snake_y] in snake_list[-2:]:
snake_x = snake_list[-1][0]
snake_y = snake_list[-1][1]
else:
snake_move([snake_x, snake_y])
- 蛇的身体的每个小块对应列表内的一个坐标,头的位置处于列表最后一项。
- 当移动时消除第一个坐标所在的位置,使用pop(0)方法弹出第一项
- 将下一个头的位置(由 snake_ctrl 函数提供)使用append()方法添加到列表最后
- 通过检测位置坐标(x in y)是否为靠近头的一段来防止蛇倒走。
四、蛇的方向控制
def get_key():#获得键盘输入
global getkey,key
a = dll.c_getch()
if a in [esc,space]:
getkey = a
if a in [move_up,move_down,move_left,move_right]:
if ((key == move_up) and (a != move_down))or ((key == move_down) and (a != move_up)) \
or(key == 0) or((key == move_left) and (a != move_right)) \
or ((key == move_right) and (a != move_left)):
key = a
else:
pass
else:
pass
def snake_ctrl():#根据键盘输入判断方向已经功能操作
global getkey, key, snake_x, snake_y
if key == move_down:
snake_y += 1
elif key == move_up:
snake_y -= 1
elif key == move_right:
snake_x += 2
elif key == move_left:
snake_x -= 2
else:
pass
if getkey == space:
time.sleep(1)
getkey = 0
while 1:
getkey = dll.c_getch()
if getkey == space:
getkey = 0
break
elif getkey == esc:
break
else:
pass
else:
pass
检测按键输入 get_key() 以及设置相应按键实现的功能 snake_ctrl()
五、食物的设置
def putfood():#放置食物
global food_x,food_y,eat_flag
if eat_flag==1:
food_x = snake_x
food_y = snake_y
while [food_x,food_y] in snake_list:
food_x = random.randint(1, 20) * 2
food_y = random.randint(1, 19)
eat_flag = 0
dll.set_cmd(food_x,food_y)
print("●")
else :
pass
def eatfood():#吃掉食物判断
global eat_flag,snake_list,snake_x, snake_y
if ([food_x,food_y] in snake_list)and(eat_flag==0) :
eat_flag = 1
else:
pass
不得不说Python中成员判断真的很好用。
- 通过食物坐标点点是否已经包含到蛇身体的列表中来判断是否吃到食物
- 食物的产生通过随机函数(random.randint(x,y))来提供坐标
- 是否放置食物由是否吃掉的标志(eat_flag)来判断
六、游戏结束
def gameover():#游戏结束判断
if (snake_x>42)|(snake_y>19)\
|(snake_x<2)|(snake_y==0):
return 1
elif snake_list.count(snake_list[-1])>1:
return 1
else :
return 0
def over_next():#结束后的操作
global getkey,eat_flag
if gameover():
dll.set_cmd(16, 9)
print("得分:{}分".format(len(snake_list)-5))
dll.set_cmd(6, 10)
print("游戏结束,esc退出,space重新开始")
while 1:
getkey = dll.c_getch()
if getkey == esc:
os.system("cls")
dll.init_cmd(1)
os.system("exit")
break
elif getkey == space:
init_game()
eat_flag = 1
break
else:
pass
else:
pass
- 贪吃蛇撞墙的判断就简单粗暴的坐标判断,如果地图复杂可能需要使用列表将每部分墙体的起始坐标录入进行判断,贪吃蛇只需要判断头的位置就能够判断是否撞到了墙。
- 使用列表的count方法能够很简单的判断序列中有没有两相同的元素,来检测蛇有没有吃到自己。
七、主程序
if __name__ == '__main__':#主函数main
dll = ctypes.windll.LoadLibrary("set_cmd.dll") # 调用c语言程序
init()
mune()
while 1:
getkey = dll.c_getch()
if getkey == space:
break
else:
pass
init_game()
while 1:
get_key()
putfood()
eatfood()
snake_ctrl()
move()
over_next()
if getkey == esc:
os.system("cls")
dll.init_cmd(1)
os.system("exit")
break
else:
pass
get_key()
time.sleep(0.15)
- 通过两次按键 get_key() 检测来减少按键的检测缺失
- 可以通过调整循环等待时间 time.sleep(0.15) 来调整游戏内蛇的速度
八、演示效果
生成.exe文件需要用到pyinstaller,没有的话需要进行以下步骤
- 运行命令符输入 pip install pyinstaller
- 等待安装完成,输入 pyinstaller -F xxx.py (文件位置)
以下是演示效果
评价:能玩
总结
虽然最后成品比较简陋,但还是有些成就感的,比之前光看书感觉效率提高很多。
下面是所有文件的网盘链接点击下载
提取码:6v5o
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/197075.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...