我又来啦,看到上一篇扫雷小游戏大家很感兴趣,这里就在写一个关于n子棋的小游戏吧!
废话不多说
直接上思路
文章图片
这里也会涉及到三个文件哦,注意代码写的位置!
n子棋的实现
- 1.游戏开始界面及选择选项
-
- 1.1菜单
- 1.2选择是否玩游戏(需要在game.c里实现游戏所有功能)
-
- 1.2.1玩家选择玩游戏
-
- 1.2.1.1初始化键盘
- 1.2.1.2展示棋盘
- 1.2.1.3真正的玩家和电脑开始下棋!!!(最难的地方)
- 2.小结
- 3.一次性展示完整的代码(需要源码的自取,之前的两篇博客忘记了添加这一步了,需要的也可以私我)
1.游戏开始界面及选择选项 1.1菜单
//test.c
void menu()
{
printf("*****************************\n");
printf("*****1. play0. exit *****\n");
printf("*****************************\n");
}
ps:
这种菜单基本上适用于自己写的一些小游戏,可以记住这个写法哦
1.2选择是否玩游戏(需要在game.c里实现游戏所有功能)
//test.c
int main()
{
int input = 0;
do
{
menu();
//打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
ps:
整体是使用的switch来实现选择的功能,写法很简单,这里提一下while(input)这样写的妙处。
但玩家想玩游戏时并且想有多次玩游戏的机会,会输入1,而while(1)为真,故一直在循环里。而当输入0,跳出循环,正好满足的玩家不想玩游戏的想法
1.2.1玩家选择玩游戏
#test.c
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board, ROW, COL);
DispalyBoard(board, ROW, COL);
//下棋
while (1)
{
PlayerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DispalyBoard(board, ROW, COL);
}
【c语言|n子棋,你能下赢电脑吗,来玩玩吧】ps:这里是整个game的思路,具体功能得在game.c里实现
1.2.1.1初始化键盘
//game.c
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;
i < row;
i++)
{
for (j = 0;
j < col;
j++)
{
board[i][j] = ' ';
}
}
}
ps:
最开始创建数组的时候,给数组的是0,这里为了展示棋盘,所以要放空格进去。
1.2.1.2展示棋盘
//game.c
//第一个版本
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// for (i = 0;
i < row;
i++)
// {
////打印数据
//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
////打印分割信息
//if(i
ps:这里对棋盘的理解是个重点,先看看棋盘该有的样子吧
![c语言|n子棋,你能下赢电脑吗,来玩玩吧](http://img.readke.com/220811/20135164c-1.jpg)
文章图片
第一个版本的写法,是将棋盘理解成五行五列,而第二个版本,是用2 2 1的方式来理解五行五列,整体效果一样,都可以完美的打印出来
1.2.1.3真正的玩家和电脑开始下棋!!!(最难的地方)
//game.c
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
//坐标范围合法的判断
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,不能下棋,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
//0~2
y = rand() % col;
//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}//满了就返回1
//不满返回0
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;
i < row;
i++)
{
for (j = 0;
j < col;
j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}char IsWin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
for (i = 0;
i < row;
i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
//
}
} //列
int j = 0;
for (j = 0;
j < col;
j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
} if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
} //没有人赢,就要平局
if (IsFull(board, row, col))
{
return 'Q';
} //游戏继续
return 'C';
}
//test.c
int main()
{
srand((unsigned int)time(NULL));
//设置随机数的生成起点的 int input = 0;
do
{
menu();
//打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
ps:
1.先分析玩家下棋的时候,注意我们是为了给别人完,并不是所有的人都懂数组特殊之处(下标从0开始),所有我们要人性化一点,将玩家输入的正常坐标减1来对应到真正的数组位置
2.玩家和电脑每一次下棋的时候,都要判断该位置是否已经下过了或者说坐标超出数组范围了,这一点很重要
3.在看电脑下棋,这里有了一个常见而且重要的点就是生成足够随机的随机数,所以这个方法一定要一上手就能写出来
4.最后一点就是判断输赢了,这个函数需要判断横着一条线,竖着一条线,斜着的两条线,是否能满足一方获胜,或者数组已经满了,只能判成平局了。还有就是此刻没有胜出,数组也没满,继续游戏
2.小结 1.game.h文件内可以宏定义一下棋盘的行和列,如果以后想改变游戏难度的话,可以在这里一键改变棋盘大小,很省事!
2.由于game.c和test.c中需要include的一些文件都是共同的,而且都要引用game.h,所以可以将这二者需要include的全部放到game.h,最后引用game,h就好了
3.最后就是想说,没有完美的代码,代码有什么问题或者没有理解代码的意思的都欢迎评论或者私信我,我很期待你们的看法,也再次感谢大家能来看我的博客,不妨点个关注,我们下期再见!
3.一次性展示完整的代码(需要源码的自取,之前的两篇博客忘记了添加这一步了,需要的也可以私我)
//test.c
#define _CRT_SECURE_NO_WARNINGS#include "game.h"void menu()
{
printf("*****************************\n");
printf("*****1. play0. exit *****\n");
printf("*****************************\n");
}void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board, ROW, COL);
DispalyBoard(board, ROW, COL);
//下棋
while (1)
{
PlayerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DispalyBoard(board, ROW, COL);
}int main()
{
srand((unsigned int)time(NULL));
//设置随机数的生成起点的 int input = 0;
do
{
menu();
//打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
//game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;
i < row;
i++)
{
for (j = 0;
j < col;
j++)
{
board[i][j] = ' ';
}
}
}//第一个版本
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// for (i = 0;
i < row;
i++)
// {
////打印数据
//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
////打印分割信息
//if(i\n");
while (1)
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
//坐标范围合法的判断
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,不能下棋,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
//0~2
y = rand() % col;
//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}//满了就返回1
//不满返回0
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;
i < row;
i++)
{
for (j = 0;
j < col;
j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}char IsWin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
for (i = 0;
i < row;
i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
//
}
} //列
int j = 0;
for (j = 0;
j < col;
j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
} if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
} //没有人赢,就要平局
if (IsFull(board, row, col))
{
return 'Q';
} //游戏继续
return 'C';
}
//game.h
#pragma once#include .h>
#include .h>
#include #define ROW 3
#define COL 3//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
//找没有下棋的随机下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
//char IsWin(char board[ROW][COL], int row, int col);
推荐阅读
- c语言|你能用多少种方法字符串中的字符反向排列,要不看看我的
- c语言|c语言初学者对scanf函数难分辨理解的两个点(欢迎补充)
- c语言药店管理系统|药店管理系统(c语言链表实现)
- java|Java学习资料分享
- 51单片机笔记|(十四)51单片机——LCD1602实现滚动效果
- 单片机|单片机 c语言 d,单片机89C51与A/D转换器MAX - 控制/MCU - 电子发烧友网
- 单片机从入门到高级|51单片机——AD/DA转换
- 算法|C语言RGB转Lab色域
- c语言基础知识讲解|二维数组零碎知识梳理