刚学C不久,因为作业需要,制作了一个三子棋小游戏,代码很简单,适合新手练手,希望可以帮助到和我一样有需要的朋友。
思路
对于很多初学者朋友来说,其实是没有模块化的习惯的,我也是在不断自学中才逐渐有了这样的习惯。对于这样功能单一的小游戏来说,只要将游戏的主要流程弄清楚,将各个功能剥离出来,用函数将各个功能与流程逐一实现,再用一个主函数调整各个函数的入口顺序,便能实现一个类似的小游戏。
游戏主要流程
- 欢迎界面
- 初始化
- 打印棋盘
- 玩家输入
- 位置是否合法判断
- 输赢判断
- 电脑输入
- 输赢判断
- 结束
- 主函数
欢迎界面
为了不让游戏过于简陋,我制作了一个开始界面。
这是代码,三子棋这三个字拼得有点丑,不要在意这些细节哈。
int start()
{
color(2);//颜色设置
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf(" _________ \n");
printf(" __________ / | __|__|__ \n");
printf(" ______/___ __|__ |__| \n");
printf(" _______ | /|\\ |__| \n");
printf(" | / | \\ __|__|__ \n");
printf(" _______________ \\_| | / \\ \n");
int n;
SetPos(43,18);//光标位置设置,表示下面的输出在窗口的哪个位置,看不懂可以自己打空格和换行来该位置,但用函数还是比较方便。
color(11);
printf("三 子 棋 小 游 戏");
color(14);
for(int i=20;i<=26;i++)//打印选择框架
{
for(int j=27;j<=74;j++)
{
SetPos(j,i);
if(i==20||i==26)
printf("-");
else if(j==27||j==74)
printf("|");
}
}
color(10);
SetPos(35,22);
printf("1.开始游戏");
SetPos(55,22);
printf("2.退出游戏");
SetPos(35,24);
printf("3.游戏说明");
color(3);
SetPos(29,27);
printf("请选择[1 2 3]:");
color(14);
scanf("%d",&n);
return n;//返回选择的选项,通过该数字来进行下一步操作。
}
这里可能涉及到了对于初学者来说的两个新知识,color和SetPos,我先上代码
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
void SetPos(int x,int y)
{
COORD pos={x,y};//位置坐标结构体
HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);//获得句柄赋值给h
SetConsoleCursorPosition(h,pos);
}
这两个函数都涉及到了句柄的使用,以后编程经常会碰到的,句柄其实就相当于一个名字,你要对窗口进行操作的话,首先得知道他的名字吧,要让电脑知道你要操作什么。这两个函数可以直接当固定模板用的,不过要引用“windows.h”头文件。不懂的话复制粘贴一下就知道怎么用了。
初始化
因为是三子棋,所以首先我们应该建立一个3*3的字符串组,用来储存棋盘上的棋子,初始化就是将这个字符串组用空格填充,这样可以方便我们之后游戏对是否有棋子在棋盘上进行判断,同时也可防止出现乱码。
void init(char arr[3][3])//这个代码应该都能看懂吧,我就不解释了哈
{
for (int i=0;i<3;++i)
{
for (int j=0;j<3;++j)
{
arr[i][j]=' ';
}
}
}
打印棋盘
棋盘的打印是这个游戏的关键,因为这是你的游戏界面,你要看好久的。
void face(char arr[3][3])
{
system("cls");//这个是windows的一个命令函数,意思是“清屏”,每次打印前都要将上一次的棋盘清除掉再重新打印,不懂的话可以试试把这个注释掉在运行一下,看看区别在哪里。
color(15);//颜色设置
for(int i=1;i<=3;i++)
{
printf(" \n");
}
printf(" 您第一次输入的是纵坐标\n");
for(int i=1;i<=3;i++)
{
printf(" \n");
}
printf(" 输入空格后输入横坐标\n");
printf(" \n");
printf(" +---+---+---+---+\n");
printf(" | 0 | 1 | 2 | 3 |\n");
for (int i = 0; i < 3; ++i)
{
printf(" +---+---+---+---+\n");
printf(" | %d | %c | %c | %c |\n", i+1,arr[i][0],arr[i][1],arr[i][2]);
}
printf(" +---+---+---+---+\n");
}
这里就是没有使用SetPos的时候,用空格和换行更改的棋盘打印位置,棋盘的格式如果不满意的话可以自己改哦。
玩家输入
这一块是整个游戏的核心之一,其实就是向棋盘上输入棋子,也就是向字符串组中输入字符。这里是通过输入坐标的形式,检查在字符串组中该坐标上是否有棋子,没有就打印在棋盘上,有就重新输入。
这个是判断输入的棋子是否在棋盘范围内的函数。
bool lagel(int x,int y)//bool是一种返回值只为“TURE”或“FALSE”的变量类型,其实也就相当于进行判断后,返回一个结果。
{
if ((x>0)&&(x<4)&&(y>0)&&(y<4))
return true;
return false;
}
这个函数是用于判断棋盘上是否有棋子的。
void introduction(char arr[3][3],int x,int y)
{
void input_1(char arr[3][3]);
if (arr[x-1][y-1]==' ')//如果为空格,表示没有棋子,就将该玩家输入的位置填充上棋子。
arr[x-1][y-1]='X';
else//如果有棋子,则重新输入
{
printf("请勿重复输入\n");
input_1(arr);
}
}
void input_1(char arr[3][3])
{
int x,y;
printf("请选择您的落子位置: ");
scanf("%d%d",&x,&y);
if (lagel(x,y))//调用lagel函数进行判断,如果位置合法则进行下一步判断
{
introduction(arr,x,y);//调用introduction函数
}
else
{
printf("位置非法");//输入位置不在棋盘中,重新输入。
face(arr);
input_1(arr);
}
}
输赢判断
判断游戏是否继续进行,在每次玩家输入后和电脑输入后都要进行一次判断,以确定是否继续进行游戏。
int is_continue(char arr[3][3],int count)//应该都能看懂吧,就是判断有没有三个连着的,或者棋盘还有没有位置。
{
for (int i=0;i<3;++i)
{
if ((arr[i][0]==arr[i][1])&&(arr[i][1]==arr[i][2])&&(arr[i][0]!=' '))
{
end_1(arr[i][0]);
return 0;
}
}
for (int i=0;i<3;++i)
{
if ((arr[0][i]==arr[1][i])&&(arr[1][i]==arr[2][i])&&(arr[0][i]!=' '))
{
end_1(arr[0][i]);
return 0;
}
}
if ((arr[1][1]==arr[2][2])&&(arr[2][2]==arr[0][0])&&(arr[1][1]!=' '))
{
end_1(arr[1][1]);
return 0;
}
if ((arr[1][1]==arr[0][2])&&(arr[0][2]==arr[2][0])&&(arr[1][1]!=' '))
{
end_1(arr[1][1]);
return 0;
}
if (count==0)
{
face(arr);
end_1('p');
return 0;
}
return 1;
}
结束函数,打印游戏结果。
void end_1(char c)
{
switch (c)
{
case 'X':
printf("您赢了\n");
break;
case 'O':
printf("您输了\n");
break;
case 'p':
printf("和局\n");
}
}
主函数
控制各个函数的入口和顺序,也是整个游戏的灵魂,如果看过上面的代码的话,看懂这个应该没问题。
int main()
{
char arr[3][3];
int f=1,count=9,n;
n=start();
if(n==3)
n=exp();
init(arr);
face(arr);
if(n==1)
{
while (f)
{
input_1(arr);
count--;
face(arr);
f=is_continue(arr,count);
if (f==0)
break;
Sleep(720);
input_2(arr);
face(arr);
count--;
if(count==7) printf("斟酌落子哦,虽然这个人机很憨\n");
else if(count==5) printf("下一步秒杀它好吗,别放水\n");
f=is_continue(arr,count);
if (f==0)
break;
}
system("pause");
}
return 0;
}
完整代码
下面是完整代码,才学C不久,有什么问题大佬们指教一下,谢谢!
#include<stdio.h>
#include<Windows.h>
#include<time.h>
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
void SetPos(int x,int y)
{
COORD pos={x,y};
HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(h,pos);
}
int exp()
{
system("cls");
SetPos(25,8);
printf("欢迎来到三子棋小游戏");
SetPos(25,11);
printf("这个游戏又名“有手就行”");
SetPos(25,14);
printf("使用键盘输入坐标并用空格隔开");
SetPos(25,17);
system("pause");
return 1;
}
int start()
{
color(2);
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf(" _________ \n");
printf(" __________ / | __|__|__ \n");
printf(" ______/___ __|__ |__| \n");
printf(" _______ | /|\\ |__| \n");
printf(" | / | \\ __|__|__ \n");
printf(" _______________ \\_| | / \\ \n");
int n;
SetPos(43,18);
color(11);
printf("三 子 棋 小 游 戏");
color(14);
for(int i=20;i<=26;i++)
{
for(int j=27;j<=74;j++)
{
SetPos(j,i);
if(i==20||i==26)
printf("-");
else if(j==27||j==74)
printf("|");
}
}
color(10);
SetPos(35,22);
printf("1.开始游戏");
SetPos(55,22);
printf("2.退出游戏");
SetPos(35,24);
printf("3.游戏说明");
color(3);
SetPos(29,27);
printf("请选择[1 2 3]:");
color(14);
scanf("%d",&n);
return n;
}
void face(char arr[3][3])
{
system("cls");
color(15);
for(int i=1;i<=3;i++)
{
printf(" \n");
}
printf(" 您第一次输入的是纵坐标\n");
for(int i=1;i<=3;i++)
{
printf(" \n");
}
printf(" 输入空格后输入横坐标\n");
printf(" \n");
printf(" +---+---+---+---+\n");
printf(" | 0 | 1 | 2 | 3 |\n");
for (int i = 0; i < 3; ++i)
{
printf(" +---+---+---+---+\n");
printf(" | %d | %c | %c | %c |\n", i+1,arr[i][0],arr[i][1],arr[i][2]);
}
printf(" +---+---+---+---+\n");
}
void init(char arr[3][3])
{
for (int i=0;i<3;++i)
{
for (int j=0;j<3;++j)
{
arr[i][j]=' ';
}
}
}
bool lagel(int x,int y)
{
if ((x>0)&&(x<4)&&(y>0)&&(y<4))
return true;
return false;
}
void introduction(char arr[3][3],int x,int y)
{
void input_1(char arr[3][3]);
if (arr[x-1][y-1]==' ')
arr[x-1][y-1]='X';
else
{
printf("请勿重复输入\n");
input_1(arr);
}
}
void input_2(char arr[][3])
{
int x = rand()%3;
int y = rand()%3;
if (arr[x][y]==' ')
arr[x][y]='O';
else
input_2(arr);
}
void input_1(char arr[3][3])
{
int x,y;
printf("请选择您的落子位置: ");
scanf("%d%d",&x,&y);
if (lagel(x,y))
{
introduction(arr,x,y);
}
else
{
printf("位置非法");
face(arr);
input_1(arr);
}
}
void end_1(char c)
{
switch (c)
{
case 'X':
printf("您赢了\n");
break;
case 'O':
printf("您输了\n");
break;
case 'p':
printf("和局\n");
}
}
int is_continue(char arr[3][3],int count)
{
for (int i=0;i<3;++i)
{
if ((arr[i][0]==arr[i][1])&&(arr[i][1]==arr[i][2])&&(arr[i][0]!=' '))
{
end_1(arr[i][0]);
return 0;
}
}
for (int i=0;i<3;++i)
{
if ((arr[0][i]==arr[1][i])&&(arr[1][i]==arr[2][i])&&(arr[0][i]!=' '))
{
end_1(arr[0][i]);
return 0;
}
}
if ((arr[1][1]==arr[2][2])&&(arr[2][2]==arr[0][0])&&(arr[1][1]!=' '))
{
end_1(arr[1][1]);
return 0;
}
if ((arr[1][1]==arr[0][2])&&(arr[0][2]==arr[2][0])&&(arr[1][1]!=' '))
{
end_1(arr[1][1]);
return 0;
}
if (count==0)
{
face(arr);
end_1('p');
return 0;
}
return 1;
}
int main()
{
char arr[3][3];
int f=1,count=9,n;
n=start();
if(n==3)
n=exp();
init(arr);
face(arr);
if(n==1)
{
while (f)
{
input_1(arr);
count--;
face(arr);
f=is_continue(arr,count);
if (f==0)
break;
Sleep(720);
input_2(arr);
face(arr);
count--;
if(count==7) printf("斟酌落子哦,虽然这个人机很憨\n");
else if(count==5) printf("下一步秒杀它好吗,别放水\n");
f=is_continue(arr,count);
if (f==0)
break;
}
system("pause");
}
return 0;
}