
基本思路:
蛇每吃一个食物蛇身子就增加一格,用UP, DOWN, LEFT, RIGHT控制蛇头的运动,而蛇身子跟着蛇头走,每后一格蛇身子下一步走到上一格蛇身子的位置,以此类推。
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#define BEG_X 2
#define BEG_Y 1
#define WID 20
#define HEI 20
HANDLE hout
typedef enum {UP, DOWN, LEFT, RIGHT} DIR
typedef struct Snake_body
{
COORD pos//蛇身的位置
struct Snake_body *next//下一个蛇身
struct Snake_body *prev//前一个蛇身
}SNAKE, *PSNAKE
PSNAKE head = NULL//蛇头
PSNAKE tail = NULL//蛇尾
//画游戏边框的函数
void DrawBorder()
{
int i, j
COORD pos = {BEG_X, BEG_Y}
for(i = 0i <HEI++i)
{
SetConsoleCursorPosition(hout, pos)
for(j = 0j <WID++j)
{
if(i == 0)//第一行
{
if(j == 0)
printf("┏")
else if(j == WID - 1)
printf("┓")
else
printf("━")
}
else if(i == HEI - 1)//最后一行
{
if(j == 0)
printf("┗")
else if(j == WID - 1)
printf("┛")
else
printf("━")
}
else if(j == 0 || j == WID - 1)//第一列或最后一列
printf("┃")
else
printf(" ")
}
++pos.Y
}
}
//添加蛇身的函数
void AddBody(COORD pos)
{
PSNAKE pnew = (PSNAKE)calloc(1, sizeof(SNAKE))
pnew->pos = pos
if(!head)
{
head = tail = pnew
}
else
{
pnew->next = head//新创建蛇身的next指向原先的蛇头
head->prev = pnew//原先的蛇头的prev指向新创建的蛇身
head = pnew//把新创建的蛇身作为新的蛇头
}
SetConsoleCursorPosition(hout, head->pos)
printf("◎")
}
//蛇身移动的函数
void MoveBody(DIR dir)
{
PSNAKE ptmp
COORD pos = head->pos
switch(dir)
{
case UP:
if(head->pos.Y >BEG_Y + 1)
--pos.Y
else
return
break
case DOWN:
if(head->pos.Y <BEG_Y + HEI - 2)
++pos.Y
else
return
break
case LEFT:
if(head->pos.X >BEG_X + 2)
pos.X -= 2
else
return
break
case RIGHT:
if(head->pos.X <BEG_X + (WID - 2) * 2)
pos.X += 2
else
return
break
}
AddBody(pos)//添加了一个新的蛇头
ptmp = tail//保存当前的蛇尾
tail = tail->prev
if(tail)
tail->next = NULL
SetConsoleCursorPosition(hout, ptmp->pos)
printf(" ")
free(ptmp)
}
int main()
{
int ctrl
DIR dir = RIGHT//初始蛇的方向是向右的
COORD pos = {BEG_X + 2, BEG_Y + HEI / 2}
system("color 0E")
system("mode con cols=90 lines=30")
hout = GetStdHandle(STD_OUTPUT_HANDLE)
printf(" ------------贪吃蛇的移动------------")
DrawBorder()
//自定义几个蛇的身体
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
pos.X += 2
AddBody(pos)
//控制蛇的移动
while(ctrl = getch())
{
switch(ctrl)
{
case 'w':
if(dir == DOWN)
continue
dir = UP
break
case 's':
if(dir == UP)
continue
dir = DOWN
break
case 'a':
if(dir == RIGHT)
continue
dir = LEFT
break
case 'd':
if(dir == LEFT)
continue
dir = RIGHT
break
case 'q':
return 0
}
MoveBody(dir)
}
return 0
}
扩展资料:
实现逻辑
1,可以设置光标,就能实现制定位置打印制定符号。
2,涉及一个结构体,包含两个元素坐标元素和一个结构体指针。
3,结构体串联形成链表,遍历获取成员坐标,打印符号得到蛇身。
4,不断的加头,去尾,重新遍历坐标,再打印形成蛇的移动。
5,食物产生的位置判定,不能越界,也不能与蛇身体重合。
6,蛇的转向判定,一条规则,不允许倒退。
7,转向的实现,跟行进方向决定新的关节坐标(当前头的上下左右)
8,死亡检测,是否头节点坐标是否与墙壁重合,是否与身体其他关节重合。
9,加速减速,设置刷新休眠时间实现。
参考资料来源:百度百科-C语言
贪吃蛇游戏的代码#define N 200
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,key
int score=0/*得分*/
int gamespeed=50000/*游戏速度自己调整*/
struct Food
{
int x/*食物的横坐标*/
int y/*食物的纵坐标*/
int yes/*判断是否要出现食物的变量*/
}food/*食物的结构体*/
struct Snake
{
int x[N]
int y[N]
int node/*蛇的节数*/
int direction/*蛇移动方向*/
int life/* 蛇的生命,0活着,1死亡*/
}snake
void Init(void)/*图形驱动*/
void Close(void)/*图形结束*/
void DrawK(void)/*开始画面*/
void GameOver(void)/*结束游戏*/
void GamePlay(void)/*玩游戏具体过程*/
void PrScore(void)/*输出成绩*/
/*主函数*/
void main(void)
{
Init()/*图形驱动*/
DrawK()/*开始画面*/
GamePlay()/*玩游戏具体过程*/
Close()/*图形结束*/
}
/*图形驱动*/
void Init(void)
{
int gd=DETECT,gm
initgraph(&gd,&gm,"c:\\tc")
cleardevice()
}
/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
void DrawK(void)
{
/*setbkcolor(LIGHTGREEN)*/
setcolor(11)
setlinestyle(SOLID_LINE,0,THICK_WIDTH)/*设置线型*/
for(i=50i<=600i+=10)/*画围墙*/
{
rectangle(i,40,i+10,49)/*上边*/
rectangle(i,451,i+10,460)/*下边*/
}
for(i=40i<=450i+=10)
{
rectangle(50,i,59,i+10)/*左边*/
rectangle(601,i,610,i+10)/*右边*/
}
}
/*玩游戏具体过程*/
void GamePlay(void)
{
randomize()/*随机数发生器*/
food.yes=1/*1表示需要出现新食物,0表示已经存在食物*/
snake.life=0/*活着*/
snake.direction=1/*方向往右*/
snake.x[0]=100snake.y[0]=100/*蛇头*/
snake.x[1]=110snake.y[1]=100
snake.node=2/*节数*/
PrScore()/*输出得分*/
while(1)/*可以重复玩游戏,压ESC键结束*/
{
while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/
{
if(food.yes==1)/*需要出现新食物*/
{
food.x=rand()%400+60
food.y=rand()%350+60
while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
food.x++
while(food.y%10!=0)
food.y++
food.yes=0/*画面上有食物了*/
}
if(food.yes==0)/*画面上有食物了就要显示*/
{
setcolor(GREEN)
rectangle(food.x,food.y,food.x+10,food.y-10)
}
for(i=snake.node-1i>0i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
{
snake.x[i]=snake.x[i-1]
snake.y[i]=snake.y[i-1]
}
/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
switch(snake.direction)
{
case 1:snake.x[0]+=10break
case 2: snake.x[0]-=10break
case 3: snake.y[0]-=10break
case 4: snake.y[0]+=10break
}
for(i=3i<snake.nodei++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/
{
if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
{
GameOver()/*显示失败*/
snake.life=1
break
}
}
if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||
snake.y[0]>455)/*蛇是否撞到墙壁*/
{
GameOver()/*本次游戏结束*/
snake.life=1/*蛇死*/
}
if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
break
if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/
{
setcolor(0)/*把画面上的食物东西去掉*/
rectangle(food.x,food.y,food.x+10,food.y-10)
snake.x[snake.node]=-20snake.y[snake.node]=-20
/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
snake.node++/*蛇的身体长一节*/
food.yes=1/*画面上需要出现新的食物*/
score+=10
PrScore()/*输出新得分*/
}
setcolor(4)/*画出蛇*/
for(i=0i<snake.nodei++)
rectangle(snake.x[i],snake.y[i],snake.x[i]+10,
snake.y[i]-10)
delay(gamespeed)
setcolor(0)/*用黑色去除蛇的的最后一节*/
rectangle(snake.x[snake.node-1],snake.y[snake.node-1],
snake.x[snake.node-1]+10,snake.y[snake.node-1]-10)
} /*endwhile(!kbhit)*/
if(snake.life==1)/*如果蛇死就跳出循环*/
break
key=bioskey(0)/*接收按键*/
if(key==ESC)/*按ESC键退出*/
break
else
if(key==UP&&snake.direction!=4)
/*判断是否往相反的方向移动*/
snake.direction=3
else
if(key==RIGHT&&snake.direction!=2)
snake.direction=1
else
if(key==LEFT&&snake.direction!=1)
snake.direction=2
else
if(key==DOWN&&snake.direction!=3)
snake.direction=4
}/*endwhile(1)*/
}
/*游戏结束*/
void GameOver(void)
{
cleardevice()
PrScore()
setcolor(RED)
settextstyle(0,0,4)
outtextxy(200,200,"GAME OVER")
getch()
}
/*输出成绩*/
void PrScore(void)
{
char str[10]
setfillstyle(SOLID_FILL,YELLOW)
bar(50,15,220,35)
setcolor(6)
settextstyle(0,0,2)
sprintf(str,"score:%d",score)
outtextxy(55,20,str)
}
/*图形结束*/
void Close(void)
{
getch()
closegraph()
}
程序结束,请采纳
朋友给段代码给你,这个代码不要任何控件,你只需要把以下代码复制到你的窗体代码中就行了,代码很简单,相信你能看懂!仅仅用了一个结构(ShenTi)一个数组(ZhuangTai(23, 23) As Long) 一个变量(GFangXiang)代码中自动生成了Timer1,Label1控件。以及几个函数(Randomize,Circle,Line,Erase...) 相信这些对于你来说很简单,只是没想到用这些方法来实现而已,现在你开始看看效果吧!
代码如下:
'贪吃蛇代码(无控件、全代码)
Private WithEvents Timer1 As Timer
Private WithEvents Label1 As Label
Dim GFangXiang As Boolean
Dim HWB As Single
Dim She() As ShenTi
Dim X As Long, Y As Long
Dim ZhuangTai(23, 23) As Long
Private Type ShenTi
F As Long
X As Long
Y As Long
End Type
'按键反应 ←↑↓→
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Dim C As Long
If KeyCode = 27 Then End 'ESC退出
If KeyCode = 32 Then
If Timer1.Enabled = True Then '空格暂停
Timer1.Enabled = False
Label1.Visible = True
Else '空格开始
Timer1.Enabled = True
Label1.Visible = False
End If
End If
C = UBound(She)
If GFangXiang = True Then Exit Sub
Select Case KeyCode
Case 37 '←
If She(C).F = 2 Then Exit Sub
She(C).F = 0
GFangXiang = True
Case 38 '↑
If She(C).F = 3 Then Exit Sub
She(C).F = 1
GFangXiang = True
Case 39 '↑
If She(C).F = 0 Then Exit Sub
She(C).F = 2
GFangXiang = True
Case 40 '→
If She(C).F = 1 Then Exit Sub
She(C).F = 3
GFangXiang = True
End Select
End Sub
Private Sub Form_Load()
Me.AutoRedraw = True
Me.BackColor = &HC000&
Me.FillColor = 255
Me.FillStyle = 0
Me.WindowState = 2
Set Timer1 = Controls.Add("VB.Timer", "Timer1")
Set Label1 = Controls.Add("VB.Label", "Label1")
Label1.AutoSize = True
Label1.BackStyle = 0
Label1 = "暂停"
Label1.ForeColor = RGB(255, 255, 0)
Label1.FontSize = 50
ChuShiHua '初始化
End Sub
Private Sub Form_Resize()
On Error GoTo 1:
With Me
If .WindowState <>1 Then
.Cls
.ScaleMode = 3
HWB = .ScaleHeight / .ScaleWidth
.ScaleWidth = 24
.ScaleHeight = 24
Label1.Move (Me.ScaleWidth - Label1.Width) / 2, (Me.ScaleHeight - Label1.Height) / 2
HuaTu
Me.Line (X, Y)-(X + 1, Y + 1), RGB(255, 255, 0), BF
End If
End With
1:
End Sub
Private Sub Timer1_Timer()
Dim C As Long, I As Long
On Error GoTo 2:
QingChu '清图
C = UBound(She)
Select Case She(C).F
Case 0
If ZhuangTai(She(C).X - 1, She(C).Y) = 2 Then
C = C + 1
ReDim Preserve She(C)
She(C).F = She(C - 1).F
She(C).X = She(C - 1).X - 1
She(C).Y = She(C - 1).Y
ChanShengShiWu
GoTo 1:
ElseIf ZhuangTai(She(C).X - 1, She(C).Y) = 1 Then
GoTo 2:
End If
Case 1
If ZhuangTai(She(C).X, She(C).Y - 1) = 2 Then
C = C + 1
ReDim Preserve She(C)
She(C).F = She(C - 1).F
She(C).X = She(C - 1).X
She(C).Y = She(C - 1).Y - 1
ChanShengShiWu
GoTo 1:
ElseIf ZhuangTai(She(C).X, She(C).Y - 1) = 1 Then
GoTo 2:
End If
Case 2
If ZhuangTai(She(C).X + 1, She(C).Y) = 2 Then
C = C + 1
ReDim Preserve She(C)
She(C).F = She(C - 1).F
She(C).X = She(C - 1).X + 1
She(C).Y = She(C - 1).Y
ChanShengShiWu
GoTo 1:
ElseIf ZhuangTai(She(C).X + 1, She(C).Y) = 1 Then
GoTo 2:
End If
Case 3
If ZhuangTai(She(C).X, She(C).Y + 1) = 2 Then
C = C + 1
ReDim Preserve She(C)
She(C).F = She(C - 1).F
She(C).X = She(C - 1).X
She(C).Y = She(C - 1).Y + 1
ChanShengShiWu
GoTo 1:
ElseIf ZhuangTai(She(C).X, She(C).Y + 1) = 1 Then
GoTo 2:
End If
End Select
ZhuangTai(She(0).X, She(0).Y) = 0
For I = 0 To C
Select Case She(I).F
Case 0
She(I).X = She(I).X - 1
Case 1
She(I).Y = She(I).Y - 1
Case 2
She(I).X = She(I).X + 1
Case 3
She(I).Y = She(I).Y + 1
End Select
Next
TiaoZheng
1:
GFangXiang = False
ZhuangTai(She(C).X, She(C).Y) = 1
HuaTu
Exit Sub
2: '游戏结束
If MsgBox("得分:" &UBound(She) - 2 &"分 " &vbCrLf &"游戏结束,点“是”重新开始游戏,点“否”", vbYesNo, "贪吃蛇") = vbYes Then
ChuShiHua
Else
End
End If
End Sub
'初始化
Private Sub ChuShiHua()
Me.Cls
Timer1.Enabled = True
Timer1.Interval = 50
Erase ZhuangTai
ReDim She(2)
She(0).F = 2
She(0).X = 9
She(0).Y = 11
ZhuangTai(9, 11) = 1
She(1).F = 2
She(1).X = 10
She(1).Y = 11
ZhuangTai(10, 11) = 1
She(2).F = 2
She(2).X = 11
She(2).Y = 11
ZhuangTai(11, 11) = 1
HuaTu '画图
ChanShengShiWu
End Sub
'清图
Private Sub QingChu()
Dim I As Long
For I = 0 To UBound(She)
Me.Line (She(I).X, She(I).Y)-(She(I).X + 1, She(I).Y + 1), Me.BackColor, BF
Next
End Sub
'画图 蛇
Private Sub HuaTu()
Dim I As Long
For I = 0 To UBound(She)
Me.Circle (She(I).X + 0.5, She(I).Y + 0.5), 0.49, RGB(255, 255, 0), , , HWB
Next
End Sub
Private Sub TiaoZheng()
Dim I As Long
For I = 0 To UBound(She) - 1
She(I).F = She(I + 1).F
Next
End Sub
'随机产生食物
Private Sub ChanShengShiWu()
Randomize Timer
1:
X = Int(Rnd * 24)
Y = Int(Rnd * 24)
If ZhuangTai(X, Y) >0 Then GoTo 1:
ZhuangTai(X, Y) = 2
Me.Line (X, Y)-(X + 1, Y + 1), RGB(255, 255, 0), BF
End Sub
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)