目录
前言
一、基本实现逻辑
二、实现步骤
1.实现进入游戏后的选择菜单——》这个实现起来较为容易,我们约定为:1是玩游戏, 0 是退出游戏!
2.要玩完了一局后接着玩,很容易想到要用循环。
3.采用多文件编程---》我们把实现游戏的相关代码放到game.c的文件里面,把所有头文件和函数的声明都放到game.h里面,谁用谁调用即可,把测试相关的代码都放到test.c里面。
4.创建棋盘
5.打印棋盘
6.玩家落子
7.电脑落子
8.胜负判断
三、全部游戏源码
前言
大家小时候,一定玩过三子棋也就是井字棋!它的玩法也很简单,让三个棋相连的时候就赢了!今天小编就用C语言来实现一下!如有不对的地方还请大正 小编先磕一个 Orz !
一、基本实现逻辑
在实现前理清楚实现的顺序和逻辑,在实现中就能更好地实现,不至于一开始就一顿狂敲,到后面发现一堆bug这就得不偿失了!下面我们就来梳理一下实现该小游戏的逻辑:
1.我们希望进入游戏后可以有个菜单让我们选择
2.我们希望可以重复玩(一把玩完了还可以接着玩)
3.为了使每一个模块简洁,且调试起来方便我们采用多文件的形式
4.既然是下棋就得有个棋盘---》创建一个3*3的棋盘
5.打印棋盘
6.玩家落子(坐标形式)
7.电脑落子(随机)
8.判断胜负(玩家赢/电脑赢/平局)
二、实现步骤
1.实现进入游戏后的选择菜单——》这个实现起来较为容易,我们约定为:1是玩游戏, 0 是退出游戏!
代码演示:
#include<stdio.h>
void menu()
{
printf("************************\n");
printf("********1. play ********\n");
printf("********0. exit ********\n");
printf("************************\n");
}
int main()
{
int input = 0;
menu();
printf("请输入操作数:> ");
scanf("%d", &input);
return 0;
}
这里就用一个这样的简陋的菜单作为选择界面!(小编不会用Easyx等的图形库)菜单弹出来之后,你得选择玩还是退出!因此需要一个变量来存你要选择的值!
2.要玩完了一局后接着玩,很容易想到要用循环。
但三种循环选择哪一种呢?我们想一开始你也得给玩家弹出彩单让他选择,玩或者是退出!也就是说无论是否玩都得给玩家弹出彩单让他选择!到这里大家都能想到了。没错,用do...while循环!接上面说的选择1 玩游戏,0 退出。我们改怎么处理呢?答案是用选择结构中的switch case 语句较好(if else也可以)。下面小编就来实现一下:
代码演示:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
printf("************************\n");
printf("********1. play ********\n");
printf("********0. exit ********\n");
printf("************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入操作数:> ");
scanf("%d", &input);
switch (input)
{
case 1:
printf("玩游戏!\n");
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("操作数非法,请重新输入!\n");
break;
}
} while (input);
return 0;
}
看效果:
3.采用多文件编程---》我们把实现游戏的相关代码放到game.c的文件里面,把所有头文件和函数的声明都放到game.h里面,谁用谁调用即可,把测试相关的代码都放到test.c里面。
看效果:
这里要注意的是:一般引库里面的头文件我们用<>(例如:#include<stdlib.h>),而引用自己的头文件时用""。
4.创建棋盘
我们要下棋首先得有一个棋盘,我们想三子棋的棋盘实际上就是一个3*3的字符数组(该数组应该里面放的都是空格),在里面放上(覆盖空格)不同的字符而进行下棋的;那我们先创建一个3*3的字符数组,为了让我们看到先赋值为0,达到效果后改为' ';
代码演示:
看效果:
这时候效果已经出来了,但有一个缺陷就是,这里的行和列已经写死了!如果后期有变动就改的东西很多!有没有更好地办法呢?答案是有的,我们前面初识C语言的时候说过一个东西叫#define定义的自符常量!用这个就可以!
void game()
{
//创建棋盘
char board[R][C] = { 0 };
//初始化棋盘
InitBoard(board, R, C);
//打印棋盘
DisplayBoard(board, R, C);
}
5.打印棋盘
上面已经创建弄好了棋盘,但还没有实现真正棋盘的打印,先来看看我们期盼的棋盘,
下来我们就来打印一下和他差不多的一个吧!
void DisplayBoard(char board[R][C], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf(" %c ", board[i][j]);
if(j < c - 1)
printf("|");
}
printf("\n");
if (i < r - 1)
{
for (int j = 0; j < c; j++)
{
printf("---");
if (j < c - 1)
printf("|");
}
printf("\n");
}
}
}
看效果:
这样就基本模拟出来了一个棋盘!
6.玩家落子
由于小编也还是刚刚还没入门的小菜鸡,不会高端的技术,所以我们就采用简单的,玩家下棋我们就采用坐标,玩家输入要落子的位置(行、列都是1---3),这里我猜您有疑问,数组不是下标从0开始的吗,这里怎么是1开始的,我们要理解玩家,不可能每个玩家都是程序员吧!实现思路:遍历数组,当玩家的落子位置没有被占用(是空格),用 * 号覆盖空格,如果落子位置已经被占用了,提醒玩家重新落子!
代码演示:
void PlayerMove(char board[R][C], int r, int c)
{
int x = 0;
int y = 0;
printf("玩家下棋: \n");
while (1)
{
printf("请输入落子坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("此处已经被占用,请重新落子!\n");
}
}
else
{
printf("落子坐标非法,请重新落子!\n");
}
}
}
当落子完之后给玩家反馈一下棋盘即落子后打印一遍棋盘!看效果:
OK玩家落子已解决!下面让我们来看看电脑落子吧!
7.电脑落子
电脑落子我们采用的是随机落子(在x,y都属于0---2),这里就不用x,y1--3了,因为是电脑,你让他怎样执行他就怎样执行!如何随机落子呢?我们想起来我们前面的猜数字游戏产生随机数的方法,上次是1--100,这次我们只要0-- 2即可!同样和上面玩家落子一样,得是 ' ' 时,才让落子。
代码演示:
void ComputerMove(char board[R][C], int r, int c)
{
int x = 0;
int y = 0;
printf("电脑下棋: \n");
while (1)
{
x = rand() % r;
y = rand() % c;
if (x >= 0 && x <= R && y >= 0 && y <= C)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
ok!看效果:
经测试无问题!但现在面临的一个问题是他会无限制的落子找到棋盘满了,即使三个相同的相连了还不会停止,要解决这个问题,就要判断输赢!
8.胜负判断
我们知道,三子棋当有三个相同的连起来时就结束了(某一方赢了),当棋盘满了还没有三个相同的相连时,就说明既不是玩家赢也不是电脑赢即平局了!如果棋盘没满就代表着还没有结束,继续下棋!
代码实现:
int IsFull(char board[R][C], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
//玩家赢返回'*' 电脑赢返回'#' 继续返回 'C' 平局返回'Q'
char IsWin(char board[R][C], int r, int c)
{
//行
for (int i = 0; i < r; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//列
for (int i = 0; i < c; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
return board[2][0];
//判断是否继续
if (IsFull(board, r, c) == 1)
{
return 'Q';
}
return 'C';
}
我们来玩几把试一试:
三、全部游戏源码
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define R 3
#define C 3
//初始化棋盘
void InitBoard(char board[R][C], int r, int c);
//打印棋盘
void DisplayBoard(char board[R][C], int r, int c);
//玩家下棋
void PlayerMove(char board[R][C], int r, int c);
//电脑下棋
void ComputerMove(char board[R][C], int r, int c);
//判断输赢
//玩家赢返回'*' 电脑赢返回'#' 继续返回 'C' 平局返回'Q'
char IsWin(char board[R][C], int r, int c);
game.c
#include"game.h"
void InitBoard(char board[R][C], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[R][C], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf(" %c ", board[i][j]);
if(j < c - 1)
printf("|");
}
printf("\n");
if (i < r - 1)
{
for (int j = 0; j < c; j++)
{
printf("---");
if (j < c - 1)
printf("|");
}
printf("\n");
}
}
}
void PlayerMove(char board[R][C], int r, int c)
{
int x = 0;
int y = 0;
printf("玩家下棋: \n");
while (1)
{
printf("请输入落子坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("此处已经被占用,请重新落子!\n");
}
}
else
{
printf("落子坐标非法,请重新落子!\n");
}
}
}
void ComputerMove(char board[R][C], int r, int c)
{
int x = 0;
int y = 0;
printf("电脑下棋: \n");
while (1)
{
x = rand() % r;
y = rand() % c;
if (x >= 0 && x <= R && y >= 0 && y <= C)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
int IsFull(char board[R][C], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
//玩家赢返回'*' 电脑赢返回'#' 继续返回 'C' 平局返回'Q'
char IsWin(char board[R][C], int r, int c)
{
//行
for (int i = 0; i < r; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//列
for (int i = 0; i < c; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
return board[2][0];
//判断是否继续
if (IsFull(board, r, c) == 1)
{
return 'Q';
}
return 'C';
}
test.c
#include"game.h"
void menu()
{
printf("************************\n");
printf("********1. play ********\n");
printf("********0. exit ********\n");
printf("************************\n");
}
void game()
{
//创建棋盘
char board[R][C] = { 0 };
//初始化棋盘
InitBoard(board, R, C);
//打印棋盘
DisplayBoard(board, R, C);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, R, C);
DisplayBoard(board, R, C);
//判断输赢
ret = IsWin(board, R, C);
if (ret != 'C')
break;
//电脑下棋
ComputerMove(board, R, C);
DisplayBoard(board, R, C);
//判断输赢
ret = IsWin(board, R, C);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢!\n");
else if (ret == '#')
printf("电脑赢!\n");
else
printf("平局!\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入操作数:> ");
scanf("%d", &input);
switch (input)
{
case 1:
game();
//printf("玩游戏!\n");
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("操作数非法,请重新输入!\n");
break;
}
} while (input);
return 0;
}
OK!好兄弟我们下期再见!