学习C语言基础期间无聊,随便写了个小游戏,没有学GUI,
就用纯字符写了个贪吃蛇来玩,经过五次的bug修复,总算做出了点样子
虽然网上这样的源码一so一堆,但还是靠自己的思路写了出来
有什么不足还请指出,但是望大佬勿喷...
下面是可以直接在Windows系统的编译器上编译执行的源代码:
就用纯字符写了个贪吃蛇来玩,经过五次的bug修复,总算做出了点样子
虽然网上这样的源码一so一堆,但还是靠自己的思路写了出来
有什么不足还请指出,但是望大佬勿喷...
下面是可以直接在Windows系统的编译器上编译执行的源代码:
#include <time.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
//#pragma warning(disable:4996)
//↑移除Visual Studio的4996警告
void food(int fxy[], int xy[][1369]);
void move(int dir, int xy[][1369]);
void GUI(char s[][39][3], char chs[][3], int xy[][1369], int size, int fxy[], int time);
void udlr(char s[][39][3], char chs[][3]);
void snake(int fxy[], int xy[][1369], int size);
void food(int fxy[], int xy[][1369]) {
srand(time(NULL));
//以時間為種子產生隨機數
fxy[0] = rand() % 37 + 1;
fxy[1] = rand() % 37 + 1;
//分別賦值給食物的x和y坐標
}
void cls() {
//解決system("cls")導致的閃爍問題
COORD point = { 0,0 };
//光標要移動到的坐標
HANDLE HOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(HOutput, point);
//移動光標至命令行最前端
}
void move(int dir, int xy[][1369]) {
//判斷蛇頭移動方向,并對蛇頭的x或y坐標進行相應的加減
if (dir == 1)
xy[0][0] -= 1;
else if (dir == 2)
xy[0][0] += 1;
else if (dir == 3)
xy[1][0] -= 1;
else if (dir == 4)
xy[1][0] += 1;
}
void snake(int fxy[], int xy[][1369], int size) {
//蛇身體的移動,xy[2][1369]存放了蛇頭及身體的坐標
int i;
for (i = 0; i < size - 1; i++) {
xy[0][size - i - 1] = xy[0][size - i - 2];
xy[1][size - i - 1] = xy[1][size - i - 2];
}
}
void GUI(char s[][39][3], char chs[][3], int xy[][1369], int size, int fxy[], int time) {
int x, y, z, i = 0;
char ui[39][79] = { "" }, gui[6241] = { "" }, enter[] = { "\n" };
//s[39][39][3]表示39*39的 長度為3 的字符串二維數組,用於第一次存放遊戲界面佈局
//ui[39][79]表示39個長度為79的字符串的數組,用於第二次存放遊戲界面的佈局
//gui[6241]用於第二次存放遊戲界面的佈局,以達到三次性輸出到屏幕上的目的
//↓循環給s數組賦值,形成 遊戲界面佈局
for (x = 0; x < 39; x++) {
for (y = 0; y < 39; y++) {
if (!x || !y || x == 38 || y == 38)
for (z = 0; z < 3; z++)
s[x][y][z] = chs[0][z];
else
for (z = 0; z < 3; z++)
s[x][y][z] = chs[1][z];
}
}
//↓循環將食物替換進遊戲界面佈局
for (z = 0; z < 3; z++) {
s[fxy[0]][fxy[1]][z] = chs[3][z];
}
//↓循環將蛇替換進遊戲界面佈局
for (i = 0; i < size; i++) {
//↓蛇頭
if (!i)
for (z = 0; z < 3; z++) {
s[xy[0][i]][xy[1][i]][z] = chs[4][z];
}
//↓蛇身
else
for (z = 0; z < 3; z++) {
s[xy[0][i]][xy[1][i]][z] = chs[2][z];
}
}
//↓循環將s賦值給ui,并將ui賦值給gui
for (i = 0, x = 0; x < 39; x++, i++) {
for (y = 0; y < 39; y++)
strcat(ui[i], s[x][y]);
strcat(gui, ui[i]);
strcat(gui, enter);
}
//↓輸出遊戲界面
printf("%s按ESC退出遊戲\n當前速度:%4d\n當前分數:%4d", gui, time, (size - 1) * 10);
}
void udlr(char s[][39][3], char chs[][3]) {
int mark_arrow = 0, ch = 0, dir = 0, xy[2][1369] = { {19},{19} }, fxy[2] = { 0 };
int size = 1, time, state = 0, i;
//↓第一次調用,初始化食物坐標
food(fxy, xy);
while (1) {
//↓檢測緩衝區中是否有數據
if (kbhit()) {
ch = getch();
//將緩衝區中的數據以字符的形式讀出至ch
//↓循環監聽,直到按Esc鍵退出
if (ch == 27) {
system("cls");
puts("遊戲已退出");
break;
}
//↓判斷是否為控制字符
if (ch == 224) {
mark_arrow = 1;
continue;
}
//↓判斷方向,72↑,80↓,75←,77→
if (mark_arrow) {
if (ch == 72)
dir = 1;
else if (ch == 80)
dir = 2;
else if (ch == 75)
dir = 3;
else if (ch == 77)
dir = 4;
mark_arrow = 0;
continue;
}
}
//↓循環判斷蛇頭是否碰到了蛇身
for (i = 1; i < size; i++) {
if (xy[0][i] == xy[0][0] && xy[1][i] == xy[1][0]) {
state = 1;
break;
}
}
//↓判斷蛇頭是否碰了壁,是否碰到了蛇身
if (xy[0][0] < 1 || xy[0][0] > 37 || xy[1][0] < 1 || xy[1][0] > 37 || state) {
printf("\n遊戲結束\n總得分:%4d", (size - 1) * 10);
break;
}
//↓判斷蛇頭是否吃到了食物
if (xy[0][0] == fxy[0] && xy[1][0] == fxy[1]) {
//↓蛇身體長度+1
size++;
//↓重置食物位置
food(fxy, xy);
}
snake(fxy, xy, size);
move(dir, xy);
cls();
time = 170 - (size - 1) * 2;
//暫停時間(ms),蛇的速度,越小越快
//↓防止暫停時間小於1ms
if (time <= 0)
time = 1;
GUI(s, chs, xy, size, fxy, time);
//↓暫停函數
Sleep(time);
}
}
void start() {
char s[39][39][3];
char chs[5][3] = { {"■"}, {"□"}, {"●"}, {"★"},{"◆"} };
//chs[5][3]表示5個長度為3的特殊字符數組,用於存放遊戲界面佈局的組成元素
puts("按任意鍵開始遊戲");
system("pause");
udlr(s, chs);
system("pause");
}
int main() {
start();
return 0;
}