C语言——三子棋

简介: C语言——三子棋

今天我给大家带来一个小游戏,三子棋的简单实现。跟着本篇文章,你也可以做出属于你自己的三子棋

                                                       游戏的整体思路

1.text.c————用来测试游戏

2.game.c————游戏功能的实现

3.game.h————游戏功能的声明

‘*’代表着玩家下的棋(也表示赢),‘#’代表电脑下的棋(也表示赢),‘Q’表示和棋,‘C’表示继续,

text.c————我们用来测试游戏,我们玩游戏时都会先玩一把,所以我们会选择用do while的循环来解决,当我们第一次进入时,就应该有一个菜单来问我们是否玩游戏,这就用到了我们的menu函数,然后我们可以根据我们选择来选择是否玩游戏。


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;
}

我们定义了一个int类型的临时变量input,然后我们根据input的不同来选择是否进行游戏,当我们选择1时,我们就玩游戏,选择0时就选择退出游戏,如果不是这2个数就重新选择。


这是我们来实现menu函数,我们只需要打印菜单就行,所以我们不需要传参和返回值,直接printf就可以了

void menu()
{
  printf("*************************\n");
  printf("********  1.play  *******\n");
  printf("********  0.exit  *******\n");
  printf("*************************\n");
}

  • 这样一看,我们就完成了菜单的打印。当我们选择1时,我们就进入了switch的选择,进入了game函数。
void game()
{
  char board[ROW][COL] = { 0 };
  InitBoard(board, ROW, COL);
  DisplayBoard(board, ROW, COL);
  char ret = 0;
  while (1)
  {
    PlayerMove(board, ROW, COL);
    DisplayBoard(board, ROW, COL);
    ret = IsWin(board, ROW, COL);
    if (ret != 'C')
      break;
    //电脑下
    ComputerMove(board, ROW, COL);
    DisplayBoard(board, ROW, COL);
    ret = IsWin(board, ROW, COL);
    if (ret != 'C')
      break;
  }
  if (ret == '*')
    printf("玩家赢\n");
  else if (ret == '#')
    printf("电脑赢\n");
  else
    printf("和局\n");
}

我们先定义一个3行3列的二维数组,为了我们代码的可读性,我们就可以将行改为ROW,列对应为COL,这是我们就可以在game.h中#define了

  • game. h

 

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3

game.h中,我们是把库函数都放在了game.h中,然后我们用#define定义了一下ROW ,COL的数,这样当我们想把棋盘改为5x5的时候,只需要改变game.h的值就可以实现所有的改变。

回到text.c中,我们定义完char类型的二维数组,我们就要初始化它,将二维数组全部初始化为‘ ’。  这时我们就需要在game.h中声明一下InitBoard的函数,将我们的二维数组、行、列全部传进去。


game.h中我们就可以这样声明

void InitBoard(char board[ROW][COL], int row,int col);

然后我们函数的实现就让在了game.c中,

void InitBoard(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++)
    {
      board[i][j] = ' ';
    }
  }
}

我们想,把棋盘初始化后,是不是要显示棋盘,我们就要用到我们的DisPlayBoard的函数,目标是实现这个图。



我们发现第一行是由空格和|组成的,我们row是3,然而我们最后一列没有|,我们就可以分别来实现它,而第二行就是___和|组成的,最后一列也是没有|。这时可以实现DisPlayBoard函数了,代码如下。

void DisplayBoard(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++)
    {
      printf(" %c ", board[i][j]);
      if (j <col  - 1)
      {
        printf("|");
      }
    }
    printf("\n");
      for (j = 0; j < col; j++)
      {
        printf("---");
        if (j < col - 1)//col-1 == 2
          printf("|");
      }
      printf("\n");
  }
}

当然,我们也要在game.h中声明这个函数,当我们实现完显示棋盘的函数,这时我们就可以来实现用户走的函数了,我们可以定义一个PlayerMove的函数,定义一个电脑移动的函数(ComputerMove),我们在game.h中声明一下,然后就可以在game.c中实现了

void PlayerMove(char board[ROW][COL], int row, int col)
{
  int pos_x = 0;
  int pos_y = 0;
  printf("玩家输入:>");
  while (1)
  {
    printf("请输入棋盘坐标\n");
    scanf("%d %d", &pos_x, &pos_y);
    if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
    {
      if (board[pos_x-1][pos_y-1] == ' ')
      {
        board[pos_x-1][pos_y-1] = '*';
        break;
      }
      else
      {
        printf("pos is occupied\n");
      }
    }
    else
    {
      printf("pos is error\n");
    }
  }
}

我们定义pos_x和pos_y来表示要走的位置,我们落的棋子就必须在棋盘中,这就有了第一个if的判断,第二个if判断中如果落得那个位置是‘ ’,就代表了那个位置没有人下,我们就可以把“*”下在那个位置,然后挑出循环,如果下的位置有人落了,我们就要重新下,循环一下就可以实现了。但请注意,我下的位置是[pos_x-1][pos_y],这是因为我们的数组下标是从0开始的,而用户玩的时候,以为的1行1列就是我们的0行0列,所以我们都要-1,。

void ComputerMove(char board[ROW][COL], int row, int col)
{
  printf("电脑输入:>\n");
  while (1)
  {
    int pos_x = rand() % row;//0-row-1
    int pos_y = rand() % col;//0-col-1
    if (board[pos_x][pos_y] == ' ')
      board[pos_x][pos_y] = '#';
    break;
  }
}

电脑下的棋子当然要下在棋盘内,所以我们用到了%row,表示着0-row-1的位置,我们要在棋盘内随机落子,我们就要用到rand函数,rand函数就要用到srand函数,我们可以把srand放在main函数中,


srand(((unsigned int)time(NULL)));

这个代表着时间戳,我们显示生活中的时间都是一直在走的,这样我们就可以实现随机落子了,我们用srand函数中用到了time的类型我们就把它置位空,类型强转为(unsigned int),注意,我们的srand要把它放在while函数之前,不能放在while函数中,我们可以这样理解,如果我们把srand函数放在whlie函数中,我们是不是每次循环的时候,时间都要重新设定一下,这样就不符合我们的定义了。

然后就是我们的IsWin函数了,我们把board,row,col传参传过去,我们要实现IsWin函数,老方法需要我们在game.h中声明一下,在game.c中实现函数

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][0];//返回谁赢  '*' '#' 'Q' 'C'
  }
  for (i = 0; i < row; 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[i][i];
  if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    return board[1][1];
  if ((IsFull(board, row, col)) == 1)
    return 'Q';
    return 'C';
}

我们定义一个int类型的变零i,然后我们用for循环,进入第一个if判断,如果连着3个都相等,而且都不等于‘ ’,我们就可以返回board【i】【0】,代表着谁连3个就谁赢,第二个if判断就是判断列是否相等,第三个和第四个是判断斜对角是否3个连着的。


  • 当棋盘满了的时候,我们就返回了‘Q’,代表着和棋,如果上述三个都不满足,就表示继续下棋。
  • IsFull函数需要我们遍历一下,用for循环,代码如下,
int IsFull(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;
    }
  }
  //返回为1  if才会进去
  return 1;
}
  • 如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。
  • 最后,附上game.c的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘为空格
void InitBoard(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++)
    {
      board[i][j] = ' ';
    }
  }
}
void DisplayBoard(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++)
    {
      printf(" %c ", board[i][j]);
      if (j <col  - 1)
      {
        printf("|");
      }
    }
    printf("\n");
      for (j = 0; j < col; j++)
      {
        printf("---");
        if (j < col - 1)//col-1 == 2
          printf("|");
      }
      printf("\n");
  }
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
  int pos_x = 0;
  int pos_y = 0;
  printf("玩家输入:>");
  while (1)
  {
    printf("请输入棋盘坐标\n");
    scanf("%d %d", &pos_x, &pos_y);
    if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
    {
      if (board[pos_x-1][pos_y-1] == ' ')
      {
        board[pos_x-1][pos_y-1] = '*';
        break;
      }
      else
      {
        printf("pos is occupied\n");
      }
    }
    else
    {
      printf("pos is error\n");
    }
  }
}
int IsFull(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;
    }
  }
  //返回为1  if才会进去
  return 1;
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
  printf("电脑输入:>\n");
  while (1)
  {
    int pos_x = rand() % row;//0-row-1
    int pos_y = rand() % col;//0-col-1
    if (board[pos_x][pos_y] == ' ')
      board[pos_x][pos_y] = '#';
    break;
  }
}
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][0];//返回谁赢  '*' '#' 'Q' 'C'
  }
  for (i = 0; i < row; 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[i][i];
  if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    return board[1][1];
  if ((IsFull(board, row, col)) == 1)
    return 'Q';
    return 'C';
}
  • 如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。
  • 最后,附上game.c的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘为空格
void InitBoard(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++)
    {
      board[i][j] = ' ';
    }
  }
}
void DisplayBoard(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++)
    {
      printf(" %c ", board[i][j]);
      if (j <col  - 1)
      {
        printf("|");
      }
    }
    printf("\n");
      for (j = 0; j < col; j++)
      {
        printf("---");
        if (j < col - 1)//col-1 == 2
          printf("|");
      }
      printf("\n");
  }
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
  int pos_x = 0;
  int pos_y = 0;
  printf("玩家输入:>");
  while (1)
  {
    printf("请输入棋盘坐标\n");
    scanf("%d %d", &pos_x, &pos_y);
    if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
    {
      if (board[pos_x-1][pos_y-1] == ' ')
      {
        board[pos_x-1][pos_y-1] = '*';
        break;
      }
      else
      {
        printf("pos is occupied\n");
      }
    }
    else
    {
      printf("pos is error\n");
    }
  }
}
int IsFull(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;
    }
  }
  //返回为1  if才会进去
  return 1;
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
  printf("电脑输入:>\n");
  while (1)
  {
    int pos_x = rand() % row;//0-row-1
    int pos_y = rand() % col;//0-col-1
    if (board[pos_x][pos_y] == ' ')
      board[pos_x][pos_y] = '#';
    break;
  }
}
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][0];//返回谁赢  '*' '#' 'Q' 'C'
  }
  for (i = 0; i < row; 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[i][i];
  if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    return board[1][1];
  if ((IsFull(board, row, col)) == 1)
    return 'Q';
    return 'C';
}
  • game.h的代码
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row,int col);
void DisplayBoard(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);
char IsWin(char board[ROW][COL], int row, int col);
  • text.c的代码  
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
  printf("*************************\n");
  printf("********  1.play  *******\n");
  printf("********  0.exit  *******\n");
  printf("*************************\n");
}
void game()
{
  char board[ROW][COL] = { 0 };
  InitBoard(board, ROW, COL);
  DisplayBoard(board, ROW, COL);
  char ret = 0;
  while (1)
  {
    PlayerMove(board, ROW, COL);
    DisplayBoard(board, ROW, COL);
    ret = IsWin(board, ROW, COL);
    if (ret != 'C')
      break;
    //电脑下
    ComputerMove(board, ROW, COL);
    DisplayBoard(board, ROW, COL);
    ret = IsWin(board, ROW, COL);
    if (ret != 'C')
      break;
  }
  if (ret == '*')
    printf("玩家赢\n");
  else if (ret == '#')
    printf("电脑赢\n");
  else
    printf("和局\n");
}
int main()
{
  int input = 0;
  srand(((unsigned int)time(NULL)));  
  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;
}


最后:这样我们就实现了简单的三子棋,当然我们也有问题,当我们的棋盘变成10x10时,我们IsWin的判断就有问题了,我们也只能判断3子棋,如果有兴趣,可以适当改一下代码,让它变成多子棋。 

相关文章
|
6月前
|
C语言
以c语言为基础实现的简易三子棋
以c语言为基础实现的简易三子棋
40 1
|
6月前
|
C语言
c语言简单三子棋
c语言简单三子棋
|
6月前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
59 1
|
6月前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
6月前
|
C语言
用c语言实现三子棋
用c语言实现三子棋
26 0
|
5月前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
28 1
|
6月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
62 1
|
6月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
70 1
|
5月前
|
存储 C语言
三子棋(C语言版)
三子棋(C语言版)
|
6月前
|
编译器 C语言
【C语言入门小游戏】三子棋
【C语言入门小游戏】三子棋
51 0
【C语言入门小游戏】三子棋