前言
我们前面学到了c语言的很多相关的知识,那么我们能不能用我们所学的知识写出一个三子棋呢?答案是肯定可以的。接下来会跟大家分析三子棋具体的一个实现思路,看官,干货来了,打起精神哦!
一、创建文件
如果不知道怎么创建项目的话可以看看我之前写的文章
http://t.csdn.cn/hh55ghttp://t.csdn.cn/hh55g 首先我们创建一个头文件game.h用于存放头文件,函数定义以及宏定义。接着创建一个game.c用于存放函数,最后创建一个test.c用于调用函数来实现游戏的运行。
这样做的好处是,当我们的技术学到炉火纯青的时候,有人委托我们做项目的话,一是可以保护我们的劳动成果,二是方便后期的维护和项目升级。
二、实现步骤
1.创建菜单
我们首先要想到的是三子棋是一个游戏,用户如何才能使用我们的三子棋是我们的出发点,所以我们需要实现一个菜单来让用户明白如何操作。
#include<stdio.h>
void menu()//进来了直接打印菜单
{
printf("三子棋小游戏(按1开始)\n");
printf("********************************\n");
printf("********** 1.开始游戏. **********\n");
printf("********** 0.退出游戏. **********\n");
printf("********************************\n");
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do {
menu();//进入菜单
printf("请选择-->");
scanf("%d", &input);
switch (input)
{
case 1://1进入游戏操作界面
{
game(); printf("\n");
break;
}
case 0://0表示不想玩了,就要退出游戏
{
printf("退出游戏\n");
break;
}
default:输入选项不是0和1则显示输入错误
{
printf("输入错误,请重新输入\n");
break;
}
}
} while (input);//do while的好处是不管什么情况都给你先显示一遍菜单,小游戏很多都用的这个循环。
return 0;
}
2.game函数实现
我们此时无非三种情况,用户输入非0非1的数字,用户重新输入;用户输入0,游戏退出;用户输入1,game函数运行。
首先三子棋,那么我们需要有一个下棋的棋盘吧,我们先实现完打印看看。
思路大致是,先创建一个存放棋盘的数组,初始化棋盘,最后没问题的话就打印棋盘。
void init_sdf(char sdf[ROW][COL], int row, int col)
{//前面讲到了sdf是我们定义的数组名
//我们用ROW代表行,COL代表列
//ROW和COL我都定义为了3
//即三行三列的棋盘
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
sdf[i][j] = ' ';
}
void display_sdf(char sdf[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", sdf[i][j]);
if (j < col - 1)
printf("|");
}printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}printf("\n");
}
}
}有一些线可能不是必要的,但使用起来会使界面更自然好看。
打印出这样就算是棋盘实现成功了,接着我们要实现的就是玩家下棋和电脑下棋,以及最重要计算是否胜利。
2.1game函数实现
void player_move(char sdf[ROW][COL], int row, int col)
{
int x = 0; int y = 0; printf("玩家下棋\n");
printf("请输入要输入的坐标\n");
scanf("%d %d", &x, &y);
while(1)
{
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (sdf[x - 1][y - 1] == ' ')
{
sdf[x - 1][y - 1] = '*';
break;
}//我们数组下标是从0开始的
//但为了方便用户理解,第一个方格则为[1][1]
//实际输入是[0][0]
else
{
printf("该坐标已有棋,请重新输入\n");
break;
}
}
else
{
printf("不合理坐标,请重新输入\n");
}
}
}
void computer_move(char sdf[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
while (1)
{//为了体现电脑下棋的随机性
//我们调用了时间戳来实现
// main函数里面的这段也是时间戳的部分
//srand((unsigned)time(NULL));
int x = rand() % row;
int y = rand() % col;
if (sdf[x][y] == ' ')
{
sdf[x][y] = '#';
break;
}
}
}
//如果棋盘满了,返回1
//不满,返回0
//static是静态的意思
// 表示只能在这个文件内使用
//表示这个函数不能跨文件使用
static char is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (' ' == board[i][j])
{
return 0;
}
}
}
return 1;
}
//计算胜利函数
//三子棋是3*3
//那么胜利条件就有横,竖,斜三种情况
char is_win(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][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < col; 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[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 (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
char ret;
while (1)
{
player_move(sdf, ROW, COL);
display_sdf(sdf, ROW, COL);
ret = is_win(sdf, ROW, COL);
if (ret != 'C')
{
break;
}
computer_move(sdf, ROW, COL);
display_sdf(sdf, ROW, COL);
ret = is_win(sdf, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*') {
printf("玩家赢\n");
}
else if (ret == '#') {
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
实现三子棋并不难,主要还是一些细节的东西要注意,可能输错了某个字母导致程序中断。
源码在此处,供交流学习
game.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<windows.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define ROW 3
#define COL 3
void init_sdf(char sdf[ROW][COL], int row, int col);
void display_sdf(char sdf[ROW][COL], int row, int col);
void player_move(char sdf[ROW][COL], int row, int col);
void computer_move(char sdf[ROW][COL], int row, int col);
char is_win(char sdf[ROW][COL], int row, int col);
char is_full(char sdf[ROW][COL], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void init_sdf(char sdf[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
sdf[i][j] = ' ';
}
void display_sdf(char sdf[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", sdf[i][j]);
if (j < col - 1)
printf("|");
}printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}printf("\n");
}
}
}
void player_move(char sdf[ROW][COL], int row, int col)
{
int x = 0; int y = 0; printf("玩家下棋\n");
printf("请输入要输入的坐标\n");
scanf("%d %d", &x, &y);
while(1)
{
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (sdf[x - 1][y - 1] == ' ')
{
sdf[x - 1][y - 1] = '*';
break;
}//我们数组下标是从0开始的
//但为了方便用户理解,第一个方格则为[1][1]
//实际输入是[0][0]
else
{
printf("该坐标已有棋,请重新输入\n");
break;
}
}
else
{
printf("不合理坐标,请重新输入\n");
}
}
}
void computer_move(char sdf[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
while (1)
{//为了体现电脑下棋的随机性
//我们调用了时间戳来实现
// main函数里面的这段也是时间戳的部分
//srand((unsigned)time(NULL));
int x = rand() % row;
int y = rand() % col;
if (sdf[x][y] == ' ')
{
sdf[x][y] = '#';
break;
}
}
}
//如果棋盘满了,返回1
//不满,返回0
//static是静态的意思
// 表示只能在这个文件内使用
//表示这个函数不能跨文件使用
static char is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (' ' == board[i][j])
{
return 0;
}
}
}
return 1;
}
//计算胜利函数
//三子棋是3*3
//那么胜利条件就有横,竖,斜三种情况
char is_win(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][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < col; 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[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 (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
#define _CRT_SECURE_NO_WARNINGS
test.c
#include "game.h"
void menu()
{
printf("三子棋小游戏(按1开始)\n");
printf("********************************\n");
printf("********** 1.开始游戏. **********\n");
printf("********** 0.退出游戏. **********\n");
printf("********************************\n");
}
void game()
{
char sdf[ROW][COL] = { 0 };
init_sdf(sdf, ROW, COL);
display_sdf(sdf, ROW, COL);
char ret;
while (1)
{
player_move(sdf, ROW, COL);
display_sdf(sdf, ROW, COL);
ret = is_win(sdf, ROW, COL);
if (ret != 'C')
{
break;
}
computer_move(sdf, ROW, COL);
display_sdf(sdf, ROW, COL);
ret = is_win(sdf, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*') {
printf("玩家赢\n");
}
else if (ret == '#') {
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do {
menu();
printf("请选择-->");
scanf("%d", &input);
switch (input)
{
{
case 1:
game();
printf("\n");
break;
}
{
case 0:
printf("退出游戏\n");
break;
}
/*if (input != 0 && input != 1)
{
printf("请重新输入\n");
}*/
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
小结
为今为止的第四篇博客,在语言学习的路上才算刚开始,有什么错误写的不好的地方欢迎指正,一起成长进步,共攀彼岸寻逻辑与真理!