I am trying to write a minesweeper program in C.
What I am trying to achieve here is when user steps on one cell, the cells near without bombs and hint numbers will be revealed.
For example, if x is the cell stepped on, o is an empty but concealed square, . is an empty but revealed cell and * is the bomb (hidden when playing of course):
x o o o o
o o o * o
o o o o o
will result in:
. . 1 o o
. . 1 * o
. . 1 o o
Here is part of the code:
while (1)
{
printf("Row? ");
scanf("%d", &row);
printf("column? ");
scanf("%d", &clos);
if (row < 9 && row >= 0 && clos < 8 && clos >= 0)
break;
printf("\nInvalid Location\n\n");
}
if (real_map[row][clos] =='*')
{
print_map_win(display_map,real_map);
printf("\n");
printf("Flags Left = %d\n\n\n", flag_left);
printf("Game Over\n");
exit(0);
}
else
{
if (real_map[row][clos] == ' ')
{
display_map[row][clos] = real_map[row][clos];
bonos_reveal(display_map, real_map, clos, row);
// [[[bonos_reveal is the function I am asking for]]]
printf("\n");
}
else
{
display_map[row][clos] = real_map[row][clos];
}
}
in which real_map has the hint number and bombs in it, and display_map is the current state of the map.
edit: I have the following code, and it only reveals in one direction:
int bonos_reveal(int disp_map[MAP_ROWS][MAP_COLS], int real_map[MAP_ROWS][MAP_COLS], int clos, int row)
{
disp_map[row][clos] = real_map[row][clos];
if (row < 9 && row >= 0 && clos < 8 && clos >= 0)
{
if (real_map[row][clos+1] == ' ')
{
bonos_reveal(disp_map, real_map, clos + 1, row);
}
else
{
disp_map[row][clos+1] = real_map[row][clos+1];
return 1;
}
}
else
{
return 1;
}
return 1;
}
I have no idea how to loop through the cells.
Okay, here's an example implementation. It uses the following values for tiles:
0 to 8: an unmined tile; the number represents the pre-calculated number of adjacent mines
9: a mine; this special value is defined as BOMB.
Covered tiles have 10 added to that, flagged tiles (not used here) have 20 added to that. You can test whether a tile is mined with:
board[row][col] % 10 == BOMB
I'll let the code do the explaining:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define ROWS 12
#define COLS 20
#define BOMBS 8
#define BOMB 9
void inc(int board[ROWS][COLS], int row, int col)
{
if (row < 0 || row >= ROWS) return;
if (col < 0 || col >= COLS) return;
if (board[row][col] % 10 == BOMB) return;
board[row][col]++;
}
/*
* Set up board and pre-calculate adjacent bombs
*/
void board_init(int board[ROWS][COLS])
{
int i, j, n;
for (j = 0; j < ROWS; j++) {
for (i = 0; i < COLS; i++) {
board[j][i] = 10;
}
}
n = 0;
while (n < BOMBS) {
j = rand() % ROWS;
i = rand() % COLS;
if (board[j][i] % 10 != BOMB) {
board[j][i] = 19;
inc(board, j - 1, i - 1);
inc(board, j - 1, i);
inc(board, j - 1, i + 1);
inc(board, j, i - 1);
inc(board, j, i + 1);
inc(board, j + 1, i - 1);
inc(board, j + 1, i);
inc(board, j + 1, i + 1);
n++;
}
}
}
/*
* Reveal tile and propagate revelation
*/
void board_reveal(int board[ROWS][COLS], int row, int col)
{
if (row < 0 || row >= ROWS) return; /* skip off-board tiles */
if (col < 0 || col >= COLS) return;
if (board[row][col] < 10) return; /* already revealed, skip */
if (board[row][col] >= 20) return; /* must remove flag first, skip */
if (board[row][col] % 10 == BOMB) {
int i, j;
printf("Bang!\n");
for (j = 0; j < ROWS; j++) {
for (i = 0; i < COLS; i++) {
if (board[j][i] % 10 == BOMB) board[j][i] = BOMB;
}
}
} else {
board[row][col] %= 10;
if (board[row][col] == 0) {
board_reveal(board, row - 1, col);
board_reveal(board, row, col - 1);
board_reveal(board, row, col + 1);
board_reveal(board, row + 1, col);
}
}
}
void board_print(int board[ROWS][COLS])
{
int i, j;
for (j = 0; j < ROWS; j++) {
putchar(' ');
for (i = 0; i < COLS; i++) {
const char *tile = ".12345678*##########PPPPPPPPPP";
int k = board[j][i];
putchar(tile[k]);
}
putchar('\n');
}
}
int main()
{
int board[ROWS][COLS];
srand(time(NULL));
board_init(board);
board_reveal(board, 0, 0);
board_print(board);
return 0;
}
Related
I wrote a function to print Pascal's triangle with modifications.
The sides of the triangle will appear in ascending order instead of the value 1.
Each values at the base of the triangle will continue to contain the sum of the 2 members above it.
Also need to print the max value of a given level.
Example :
Pascal Triangle With Modification Example
void printTriangle2(int rows,int level) {
int i =0,j = 0,space,res = 0, isLevel = 0,max = 0;
for (i = 0 ; i<rows ; i++){
if (i == level)
isLevel = 1;
else isLevel = 0;
for (space = 1 ; space <= rows - i ; space++) {
printf(" ");
}
for (j = 0 ; j <= i ; j++) {
if (i == 0 || j == 0)
res++;
else {
res = res * (i - j + 1) / j;
}
if (isLevel == 1) {
if (res > max)
max = res;
}
printf("%4d",res);
}
printf("\n");
}
printf(" the max value is : %d",max);
}
my output for the input rows = 5 , level = 3:
Output Example
I have an issue with the calculation of res if the value is not in the side of the triangle
res = res * (i - j + 1) / j;
What am I doing wrong?
Basically I took on this project of making a Connect Four game in C , I managed to make it work but decided to go one step further trying to make a save game / load game function for the game. I really don't know what should I even google to find the answer for this one. I need to be able to save the state of the board:
Specifically i need to save the state of the board in a .txt file.
Or at least try.
And to be able to exit the programm, and re-enter then load the game by scaning an ID given when saved.
So I have two questions :
How should i go about saving such a structure in a file.txt
How to make it so that by entering an id it corresponds to a specifical board or simplier ... imagine a list of lines in a .txt which goes
ID NAME
ID NAME
and by scanning the id you get the corresponding name
this is the code: (have fun)
//libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//define
#define BOARD_ROWS 6
#define BOARD_COLS 7
//functions
int mainMenu();
void printBoard(char *board);
int game();
int takeTurn(char *board, int player, const char *PIECES);
int checkWin(char *board);
int checkFour(char *board, int, int, int, int);
int horizontalCheck(char *board);
int verticalCheck(char *board);
int diagonalCheck(char *board);
//function for game and some game logic
int game(){
const char *PIECES = "XO";
char board[BOARD_COLS * BOARD_ROWS];
memset(board, ' ', BOARD_COLS * BOARD_ROWS);
int turn, done = 0;
for(turn = 0; turn < BOARD_COLS * BOARD_ROWS && !done; turn++){
printBoard(board);
while(!takeTurn(board, turn % 2, PIECES)){
printBoard(board);
printf("COLUMN FULL!\n");
}
done=checkWin(board);
}
printBoard(board);
if(turn == BOARD_COLS * BOARD_ROWS && !done){
printf("It's a tie!");
} else{
turn--;
printf("Player %d (%c) wins!\n", turn % 2 + 1, PIECES[turn % 2]);
}
return 0;
}
//function that prints the board
void printBoard(char *board){
int row, col;
printf("\nConnect-4\n");
printf("-----------------------------\n");
for(row = 0; row < BOARD_ROWS; row++){
for(col = 0; col < BOARD_COLS; col++){
printf("| %c ", board[BOARD_COLS * row + col]);
}
puts("|");
puts("-----------------------------");
}
puts(" 1 2 3 4 5 6 7\n");
}
//check win
int checkWin(char *board){
return (horizontalCheck(board) || verticalCheck(board) || diagonalCheck(board));
}
int checkFour(char *board, int a, int b, int c, int d){
//board[a] = won;
//board[b] = won;
//board[c] = won;
//board[d] = won;
return (board[a] == board[b] && board[b] == board[c] && board[c] == board[d] && board[a] != ' ');
}
int horizontalCheck(char *board){
int row, col, idx;
const int WIDTH = 1;
for(row = 0; row < BOARD_ROWS; row++){
for(col = 0; col < BOARD_COLS - 3; col++){
idx = BOARD_COLS * row + col;
if(checkFour(board, idx, idx + WIDTH, idx + WIDTH * 2, idx + WIDTH * 3)){
return 1;
}
}
}
return 0;
}
int verticalCheck(char *board){
int row, col, idx;
const int HEIGHT = 7;
for(row = 0; row < BOARD_ROWS - 3; row++){
for(col = 0; col < BOARD_COLS; col++){
idx = BOARD_COLS * row + col;
if(checkFour(board, idx, idx + HEIGHT, idx + HEIGHT * 2, idx + HEIGHT * 3)){
return 1;
}
}
}
return 0;
}
//diagonal check for win
int diagonalCheck(char *board){
int row, col, idx, count = 0;
const int DIAG_RGT = 6, DIAG_LFT = 8;
for(row = 0; row < BOARD_ROWS - 3; row++){
for(col = 0; col < BOARD_COLS; col++){
idx = BOARD_COLS * row + col;
if(((count <= 3) && (checkFour(board, idx, idx + DIAG_LFT, idx + DIAG_LFT * 2, idx + DIAG_LFT * 3))) ||
((count >= 3) && (checkFour(board, idx, idx + DIAG_RGT, idx + DIAG_RGT * 2, idx + DIAG_RGT * 3)))){
return 1;
}
count++;
}
count = 0;
}
return 0;
}
//function to take turns between players
int takeTurn(char *board, int player, const char *PIECES){
int row, col = 0;
printf("Player %d (%c):\nEnter number coordinate: ", player + 1, PIECES[player]);
while(1){
if(1 != scanf("%d", &col) || col < 1 || col > 7){
if(col == 0){
//saveGame();```````````````````````````````````````````````this`````````````````````````````
}
else{
while(getchar() != '\n');
printf("Number out of bounds! Try again!");
}
}else {
break;
}
}
col--;
for(row = BOARD_ROWS - 1; row >= 0; row--){
if(board[BOARD_COLS * row + col] == ' '){
board[BOARD_COLS * row + col] = PIECES[player];
return 1;
}
}
return 0;
}
//===================================================================================================================================================
//function that displays the main menu
int mainMenu(){
int selection, selectionWrong;
do{
printf("Connect-4 Game\n");
printf("_______________\n");
printf("1.Play a new game\n");
printf("2.Load already existing game\n");//print the main menu look
printf("Exit the game\n");
printf("Choose option(1-3):\n");
selectionWrong = 0;//set to 0 and if scan is correct(1,2,3) we get out of loop because it does not get in if loop
scanf("%d",&selection);
if (selection > 3 || selection < 1){//if it is wrong
selectionWrong = 1;//we set to 1 so that it loops since while will only break when it is 0 (does not get in if loop)
printf("Selection is out of bounds! Try again!\n");
}
}
while(selectionWrong);//while it get's in if loop it puts error and asks to try again
if(selection == 1) game();
if(selection == 2)
if(selection == 3) return 0;//EXIT GAME OPTION
return 0;
}
//main function
int main()
{
mainMenu();//display main menu and take choice
}
i know this is to much maybe.. but when i asked last time i got so many comments about a not specific enought question ...well now it better not be too specific :)
my code shows all 100 "lights" with values of 1 and 0, what I need to do (and not managing to..) is to show only the lights which has value of 0 (so it's these lights [and these numbers are what needs to be shown] 1, 4, 9, 16, 25, 36, 49, 64, 81, 100).
Thanks for the help.
The current code:
#include <stdio.h>
#include <conio.h>
#define lights 100
int main()
{
int arr[lights] = { 0 }, i, j;
printf("Lights that are off:\n");
for (i = 0; i <= lights; i++)
arr[i] = 1;
for (i = 1; i <= lights; i++)
{
for (j = i; j <= lights; j += i)
{
if (arr[j] == 0)
arr[j] = 1;
else if (arr[j] == 1)
arr[j] = 0;
}
}
for (i = 1; i <= lights; i++)
printf("%d ", arr[i]);
return 0;
_getch;
}
So it looks like you're trying to solve the light bulb puzzle.
There's a good solution here: http://puzzles.nigelcoldwell.co.uk/six.htm
I've fixed your code so that it works, you have to be careful with the indexing.
#define NUM_OF_LIGHTS (100)
void main(void)
{
int bulbs[NUM_OF_LIGHTS] = { 0 };
int i, j;
for (i = 1; i < (NUM_OF_LIGHTS + 1); i++)
{
for (j = i; j < (NUM_OF_LIGHTS + 1); j += i)
{
/* Toggle the indexed bulb.
* Note: adjust the array as it runs from 0 to 99, not 1 to 100.
*/
bulbs[j - 1] ^= 1;
}
}
/* Print out the result. */
printf("Lights that are off:\n");
for (i = 0; i < NUM_OF_LIGHTS; i++)
{
/* Only showing the bulb index for lights that are switched off. */
if (bulbs[i] == 0)
{
printf("%d ", i + 1);
}
}
}
My function:
int checkSE(disk board[][SIZE], disk hypotheticalDisk)
{
int i;
int j;
int row;
int col;
int player;
int opponent;
int checkSEflag;
player = hypotheticalDisk.type;
(player == 0) ? (opponent = 1) : (opponent = 0);
row = hypotheticalDisk.pos.row;
col = hypotheticalDisk.pos.col;
checkSEflag = 0;
for (i = row + 2, j = col + 2; ((i < SIZE) && (j < SIZE) && (checkSEflag == 0)); i++, j++)
{
if (board[i][j].type == player)
{
for (--i, --j; board[i][j].type == opponent; i--, j--)
{
if (i == row && j == col)
{
checkSEflag = 1;
break;
}
}
}
printf("\n%d and %d and %d", i, j, checkSEflag);
}
return checkSEflag;
}
My output:
2 and 3 and 0
2 and 3 and 0
2 and 3 and 0
2 and 3 and 0
2 and 3 and 0
.
.
.
And it keeps on going...
I want both i and j to increase until they are equal to SIZE (SIZE predefined to be 8) or until checkSEflag is assigned to be equal to 1.
It looks like the values of i and j just aren't being changed...
I tried taking them out of the loop conditions and instead placed them
in the loop body, though that didn't change anything.
I doubt the post increment operators just decided to not work so I must be doing something wrong, any ideas of what that may be?
These two lines:
for(i = row+2, j = col+2; ((i < SIZE) && (j <SIZE) && (checkSEflag == 0)); i++, j++)
...
for(--i, --j; board[i][j].type == opponent; i--, j--)
so, you are both incrementing and decrementing (i,j); try sprinkling printfs around these and see if you are both incrementing and decrementing i,j on each iteration...
I can't really see what's wrong with my check neighbors function in my game of life. It checks all the 8 neighbours then depending on the living count assigns the cell being checked to living or dead, then updates the board.
void check_neighbours (int board[][COL])
{
int living = 0, i, j, k, l;
int new_board[ROW][COL];
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if ((board[i + 1 % ROW][j % COL]) == '#')
{
living++;
}
if ((board[i - 1 % ROW ][j % COL]) == '#')
{
living++;
}
if ((board[i % ROW][j + 1 % COL]) == '#')
{
living++;
}
if ((board[i % ROW][j - 1 % COL]) == '#')
{
living++;
}
if ((board[i + 1 % ROW][j + 1 % COL]) == '#')
{
living++;
}
if ((board[i - 1 % ROW ][j + 1 % COL ]) == '#')
{
living++;
}
if ((board[i + 1 % ROW ][j - 1 % COL ]) == '#')
{
living++;
}
if ((board[i - 1 % ROW ][j - 1 % COL ]) == '#')
{
living++;
}
if (living == 3)
{
new_board[i][j] = '#';
}
if (living <= 2)
{
new_board[i][j] = '-';
if (living < 3)
{
new_board[i][j] = '-';
}
}
}
for (k = 0; k < ROW; k++)
{
for (l = 0; l < COL; l++)
{
board[k][l] = new_board[k][l];
}
}
}
}
edit: Added parentheses but still prints the same
Try sticking some brackets into your math:
board[(i + 1) % ROW]
is much safer than
board[i + 1 % ROW]
Test edge conditions before doing the living count.
for (i = 0; i < ROW; i++) {
for (j = 0; j < COL; j++) {
int living = 0;
for (int drow = -1; drow <= 1; drow++) {
int row = i+drow;
if (row < 0 || row >= ROW) continue; // over the edge
for (int dcol = -1; dcol <= 1; dcol++) {
int col = j+dcol;
if (col < 0 || col >= COL) continue; // over the edge
if (row==0 && col==0) continue;
if (board[row][col] == '#') {
living++;
}
} // endfor dcol
} // endfor drow
// This section may need review - GOL rules are unclear in post -see below
if (living == 3) {
new_board[i][j] = '#';
}
...
} // endfor j
} // endfor i
If rules follow:
Any live cell with fewer than two live neighbors dies, as if caused by under-population.
Any live cell with two or three live neighbors lives on to the next generation.
Any live cell with more than three live neighbors dies, as if by over-population.
Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
#define ALIVE ('#')
#define DEAD ('-')
#define POP_MIN 2
#define POP_MAX 3
#define POP_REPRO 3
new_board[i][j] = board[i][j];
if (board[i][j] == ALIVE) {
if (living < POP_MIN) new_board[i][j] = DEAD;
else if (living > POP_MAX) new_board[i][j] = DEAD;
} else {
if (living == POP_REPRO) new_board[i][j] = ALIVE;
}
Isn't this:
board[i + 1 % ROW]
going out of bounds? Try fixing these issues.
As Paul R suggested, you could use parentheses, in order to catch up with the higher precedence of % operator in comparison to the + operator. So change the code to this:
board[(i + 1) % ROW]
Assuming ROW = 5 and i = 4, you get:
(4 + 1) % 5 = 0 // yeah!
4 + 1 % 5 = 5 // oh dear...