前言:c语言是一门编程语言,可用于嵌入式系统以及游戏开发等领域,本文是运用c语言制作一个简易的井字棋游戏。
总体思路:创建界面-->创建并初始化二维数组(作为棋盘)-->打印棋盘-->玩家下棋逻辑-->电脑下棋逻辑-->判断胜负逻辑-->分出胜负并且重新回到游戏开始界面
.h文件如下:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void print();
void play(char(*arr)[COL], int row, int col);
步骤1:
界面的制作,并且设定好界面中的选项。这里用函数的形式将这个界面封装起来,如下图。这里我用的是do...while();循环配合上switch语句,保证玩了一把之后还能接着玩。
void print()
{
printf("*************************\n");
printf("*********1、paly*********\n");
printf("*********0、exit*********\n");
printf("*************************\n");
}
#include"game.h"
int main()
{
char arr[ROW][COL];//二维数组创建(把他作为棋盘)
int input = 0;
srand((unsigned int)time(NULL));
do
{
print();//界面函数
printf("请选择选项:");
scanf("%d", &input);
switch (input)
{
case 1:
play(arr,ROW,COL);//游戏函数
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("非法输入,请重新输入!\n");
break;
}
} while (input);
return 0;
}
步骤2:
在主函数创建一个二维数组,目的是将他当作井字棋的棋盘。当然,还要对他进行一系列的操作,例如:初始化,并对他加入一些棋盘的元素(比如:边界),让他变的像一个棋盘。
效果图:
这里我选择游戏所以所需要的函数都封装在了case 1:play()这个函数当中,使主函数看起来更加简短。二维数组初始化代码:
void Init(char(*arr)[COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
*(*(arr + i) + j) = ' ';//初始化成空格的形式
}
}
}
步骤3:
将初始化好的数组打印出来,并且加上棋盘的元素:这里为了视觉效果要注意“|”和“---”的循环打印次数,即最后一次不打印“|”和“---”。
void PrintBorad(char(*arr)[COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", *(*(arr+i)+j));
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
步骤4:
下棋逻辑:遵循着只有空格处才能下棋,落过子的地方不能再下子。并且注意用户理解:对棋盘的坐标是从1开始的,与我们对数组从0下标开始的理解不一样。
void PlayerInput(char(*arr)[COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家回合:\n");
printf("请输入要下棋的坐标(中间用空格隔开):");
while (scanf("%d%d", &x, &y)==2)
{
while (getchar() != '\n')
{
;
}
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (arr[x - 1][y - 1] == ' ')//这样写就能够将用户理解的从1开始与数组从0从开始相对应
{
arr[x - 1][y - 1] = 'O';
break;
}
else
printf("此处已下过棋子,请重新下子:");
}
else
printf("非法输入,请重新输入:");
}
}
接下来就是电脑下棋,为了让电脑能够自动下棋,因此需要生产一个随机值。这里用rand()与srand((unsigned int)time(NULL));这两个函数要互相搭配才能够生产随机值,注意:srand((unsigned int)time(NULL));写在主函数内,只需要运行一次即可。(电脑下棋无需考虑坐标开始问题)
void ComputerInput(char(*arr)[COL], int row, int col)
{
printf("电脑回合:\n");
while (1)
{
int x = rand() % 3;//生产0-2的随机数
int y = rand() % 3;
if (arr[x][y] != ' ')
{
continue;
}
else
{
arr[x][y] = 'X';
break;
}
/*if (arr[x][y] == ' ')
{
arr[x][y] = 'X';
}
else
{
;
}*/
}
}
步骤5:
判断胜负的函数,下棋的结果无非就是三种情况,胜、负、平局。对于井字棋而言,哪边优先完成3棵子的连续(竖、横、斜),就能获胜。若棋盘内下满了还没有一方能达到三子连续,则判为平局,否则为继续下棋。因此该函数需要返回一个内容告诉系统接下来的操作是什么(这里注意当都是空格时,也会判断为三子连续,因此要排除等于空格的情况)
char IsWin(char(*arr)[COL], int row, int col)//c继续 q平局 O玩家获胜 X电脑获胜
{
int i = 0;
int j = 0;
char c = 'c';
char q ='q';
//斜线确定
if (arr[0][0] == arr[1][1] && arr[1][1]== arr[2][2]&& arr[1][1] !=' ')
{
return arr[0][0];//返回坐标,更加省事
}
}
else if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1]!=' ')
{
return arr[1][1];//返回坐标,更加省事
}
//行确定
for ( i=0; i < row; i++)
{
int flag = 1;
for ( j = 0; j < col-1; j++)
{
if (arr[i][j] != arr[i][j + 1] || arr[i][j] ==' ')
{
flag = 0;
}
}
if (flag == 1)
{
return arr[i][j];//返回坐标,更加省事
}
}
}
//列确定
for (j = 0; j < col; j++)
{
int flag = 1;
for (i = 0; i< row - 1; i++)
{
if (arr[i][j] != arr[i+1][j] || arr[i][j] ==' ')
{
flag = 0;
}
}
if (flag == 1)
{
return arr[i][j];//返回坐标,更加省事
}
}
}
//平局
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (arr[i][j] == ' ')
return c;
}
}
return q;
}
步骤6:
最后将这些功能按顺序放在一起即可,每一次与电脑下棋都是一个循环,判断胜负的函数就是跳出这个循环的条件,因此该函数接收到一个值后,会根据这个值再进行相关操作。
void play(char(*arr)[COL], int row, int col)
{
Init(arr, row, col);//初始化
PrintBorad(arr, row, col);//打印棋盘
char poi = 0;
while (1)
{
PlayerInput(arr, row, col);//玩家下棋
PrintBorad(arr, row, col);
poi = IsWin(arr, row, col);
if (poi != 'c')//判断胜负
break;
ComputerInput(arr, row, col);//电脑下棋
PrintBorad(arr, row, col);
poi = IsWin(arr, row, col);//每一次下棋都会改变返回值,因此要再赋值给poi
if (poi != 'c')//判断胜负
break;
}
if (poi == 'O')
{
printf("玩家获胜!\n");
}
else if (poi == 'X')
{
printf("电脑获胜!\n");
}
else
{
printf("平局!\n");
}
}
这个也是整个游戏实现的逻辑方式,将上面的函数按顺序封装,并体现再这个game函数中就可以。