Check to see if the diagonal wins in tic tac toe - c

I have been given the code for a tic tac toe game. I produced the code to check to see if the vertical will win and have tried to check the diagonal. I was able to check the primary diagonal but can't seem to determine how to check the secondary. I thought the code i have would work but it does not. The issue I am having begins on line 172
#include <stdio.h>
#include <stdlib.h> // rand(), srand()
#include <time.h> // time()
// Size of the board (square)
const int BOARD_SIZE = 3;
// Symbols used for the board
const char BLANK_SYMBOL = ' ';
const char COMP_SYMBOL = 'O';
const char HUMAN_SYMBOL = 'X';
// Human goes first
const int HUMANS_TURN = 0;
const int COMPUTERS_TURN = 1;
// Function prototypes
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]);
int hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]);
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]);
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]);
void clearScreen(void);
//
// The main function should not be changed
//
int main(void) {
char board[BOARD_SIZE][BOARD_SIZE];
int humanWon = 0; // boolean (0/1)
int computerWon = 0; // boolean (0/1)
int move = 0;
// Seed the random number generator
srand(time(0));
initializeBoard(board);
while ((move < (BOARD_SIZE * BOARD_SIZE)) && !humanWon && !computerWon) {
clearScreen();
if ((move % 2) == COMPUTERS_TURN) {
getComputerMove(board);
} else {
printBoard(board);
getHumanMove(board);
}
computerWon = hasWon(board, COMP_SYMBOL);
humanWon = hasWon(board, HUMAN_SYMBOL);
move++;
}
clearScreen();
printBoard(board);
if (humanWon) {
printf(">>>> You won!\n");
} else if (computerWon) {
printf("<<<< I won!\n");
} else { // move >= BOARD_SIZE * BOARD_SIZE
printf("==== A Draw\n");
}
return 0;
}
//
// Initialized the board to all BLANK_SYMBOL
//
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
int row;
for (row = 0; row < BOARD_SIZE; row++) {
int col;
for (col = 0; col < BOARD_SIZE; col++) {
board[row][col] = BLANK_SYMBOL;
}
}
}
//
// Determines if the 'mark' completely fills a row, column, or diagonal
// returns 1 if yes, 0 if no
//
int hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
return hasWonHorizontal(board, mark)
|| hasWonVertical(board, mark)
|| hasWonDiagonal(board, mark);
}
//
// Determines if the 'mark' completely fills a row
// returns 1 if yes, 0 if no
//
int hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
int won = 0; // boolean (0/1). Assume lost until proven true
int row;
for (row = 0; row < BOARD_SIZE && !won; row++) {
int match = 1; // boolean (0/1)
int col;
for (col = 0; col < BOARD_SIZE; col++) {
if (board[row][col] != mark) {
match = 0;
}
}
won = match;
}
return won;
}
//
// Determines if the 'mark' completely fills a column
// returns 1 if yes, 0 if no
//
int hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
int won = 0;
int col;
for (col = 0; col < BOARD_SIZE && !won; col++) {
int match = 1;
int row;
for (row = 0; row< BOARD_SIZE; row++) {
if(board[row][col] != mark) {
match = 0;
}
}
won = match;
}
return won; // Stub -- make this return the correct value
}
//
// Determines if the 'mark' completely fills a diagonal
// returns 1 if yes, 0 if no
//
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
int won = 0;
int match = 1;
int col;
for (col = 0; col < BOARD_SIZE && !won; col++) {
if(board[col][col] != mark) {
match=0;
}
else if(board[BOARD_SIZE-col-1][col] != mark){
match=0;
}
}
won = match;
return won; // Stub -- make this return the correct value
}
//
// Gets computer move by randomly picking an unoccupied cell
//
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]) {
int row;
int col;
do {
row = rand() % BOARD_SIZE;
col = rand() % BOARD_SIZE;
} while (board[row][col] != BLANK_SYMBOL);
board[row][col] = COMP_SYMBOL;
}
//
// Gets human move by prompting user for row and column numbers
//
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]) {
int rowu;
int colu;
printf("Select the value of the row for your move: ");
scanf("%i", &rowu);
printf("Select the value of the column for you move: ");
scanf("%i", &colu);
board[rowu][colu] = HUMAN_SYMBOL;
}
//
// Prints the board to the screen. Example:
//
// 0 1 2
// +---+---+---+
// 0 | X | | |
// +---+---+---+
// 1 | | O | O |
// +---+---+---+
// 2 | | | X |
// +---+---+---+
//
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
printf(" 0 1 2\n");
printf(" +---+---+---+\n");
printf("0| %c | %c | %c |\n",board[0][0],board[0][1],board[0][2]);
printf(" +---+---+---+\n");
printf("1| %c | %c | %c |\n",board[1][0],board[1][1],board[1][2]);
printf(" +---+---+---+\n");
printf("2| %c | %c | %c |\n",board[2][0],board[2][1],board[2][2]);
printf(" +---+---+---+\n");
}
//
// Clears the screen -- uses ANSI terminal control codes
//
void clearScreen(void) {
const char ESC = 27;
printf("%c[2J%c[H", ESC, ESC);
}

The logic of your code is wrong. You are only checking the secondary diagonal if the cell on the primary diagonal does not equal mark.
You will need two separate variables to keep track of whether there is a victory on each diagonal. Your code should look like this:
int match_prime = 1, match_second = 1;
for(col = 0;col < BOARD_SIZE;++col){
match_prime = board[col][col] == mark;
match_second = board[BOARD_SIZE - col - 1][col] == mark;
}
won = match_prime || match_second;

Approach 1
Hard code the diagonal element indices.
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
int won = 0;
int match = 0;
if ( ( board[0][0] == mark &&
board[1][1] == mark &&
board[2][2] == mark ) &&
( board[0][2] == mark &&
board[1][1] == mark &&
board[2][0] == mark ) )
{
match = 1;
}
won = match;
return won; // Stub -- make this return the correct value
}
Approach 2
Use for loops and iterate over the indices.
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
int match = 1;
int won = 0;
int row = 0;
// Check the first diagonal.
for (row = 0; row < BOARD_SIZE && !won; row++) {
if(board[row][row] != mark) {
match=0;
}
}
// If the first diagonal check already produces a match,
// there is no need to check the second diagonal.
if ( match != 1 )
{
int col = BOARD_SIZE-1;
for (row = 0; row < BOARD_SIZE && !won; row++, col--) {
if(board[row][col] != mark){
match=0;
}
}
}
won = match;
return won; // Stub -- make this return the correct value
}

The functions can look the following way
//
// Determines if the 'mark' completely fills a row
// returns 1 if yes, 0 if no
//
int hasWonHorizontal( char board[BOARD_SIZE][BOARD_SIZE], char mark )
{
int won = 0; // boolean (0/1).
for ( int row = 0; row < BOARD_SIZE && !won; row++ )
{
int col = 0;
while ( col < BOARD_SIZE && board[row][col] == mark ) ++col
won = col == BOARD_SIZE;
}
return won;
}
//
// Determines if the 'mark' completely fills a column
// returns 1 if yes, 0 if no
//
int hasWonVertical( char board[BOARD_SIZE][BOARD_SIZE], char mark )
{
int won = 0;
for ( int col = 0; col < BOARD_SIZE && !won; col++ )
{
int row = 0;
while ( row < BOARD_SIZE && board[row][col] == mark ) ++row;
won = row == BOARD_SIZE;
}
return won; // Stub -- make this return the correct value
}
//
// Determines if the 'mark' completely fills a diagonal
// returns 1 if yes, 0 if no
//
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark)
{
int won = 0;
int i = 0;
while ( i < BOARD_SIZE && board[i][i ] == mark ) ++i;
won = i == BOARD_SIZE;
if ( !won )
{
i = 0;
while ( i < BOARD_SIZE && board[i][BOARD_SIZE - i - 1 ] == mark ) ++i;
won = i == BOARD_SIZE;
}
return won; // Stub -- make this return the correct value
}

Related

Is there a way to include more than one 'if' conditional for output?

I have this code below (whole code after this section). I am wanting to include more than one casse for this section of the code:
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
So far, the above prints '4' when the value '8213' is entered. This is expected since for each round of for loop the 'casse' variable gets updated, by the time it runs the last integer in the array, the value for 'casse' has undergone many replacements and the end result is the last replacement of '4'.
The objective of the code is to determine which cases (casse) have
been met. There can be more than one case (casse) being met, but as it
stands now, it only has room for one case.
#include <stdio.h>
#include <math.h>
int main(void) {
int odo, value, casse;
int i;
printf("please enter a value for the odometer:\n");
scanf("%d", &odo);
value = odo;
casse = 0;
int length = floor(log10(abs(odo))) + 1;
/* count number of digits */
int c = 0; /* digit position */
int n = value;
while (n != 0)
{
n /= 10;
c++;
}
int numberArray[c];
c = 0;
n = value;
/* extract each digit */
while (n != 0)
{
numberArray[c] = n % 10;
n /= 10;
c++;
}
for(i = 0; i < length; i++)
{
printf("%d, ", numberArray[i]);
}
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
printf("\n%d\n", casse);
return 0;
}
Output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
4
Expected output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
Not only '4', but also '3', '2'.
Rather than a single variable that keeps track of the last case, you want an array which keeps track of all cases. For a small number of cases, the array can be a fixed size, with the index as case number and the value in the array as the number of times that case was triggered:
int cases[5] = {0};
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
cases[2]++;
}
if(numberArray[i] == 2)
{
cases[3]++;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
cases[4]++;
}
}

Received an "expected expression error " when i added a function

Im trying to write a program that wont compile. The error i keep receiving reads like this
expected expression
destroyFallingStone (int map[][SIZE], int column);
It happened after i added the destroyFallingStone function and Ive checked the function and function prototype for any syntax errors. I don't know where Ive made a mistake.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SIZE 15
#define EMPTY 0
#define STONE 1
// TODO: Add any extra #defines here.
// TODO: Add any extra function prototypes here.
void printMap(int map[SIZE][SIZE], int playerX);
void destroyFallingStone (int map[][SIZE], int column);
int main (void) {
// This line creates our 2D array called "map" and sets all
// of the blocks in the map to EMPTY.
int map[SIZE][SIZE] = {EMPTY};
// This line creates out playerX variable. The player starts in the
// middle of the map, at position 7.
int playerX = SIZE / 2;
printf("How many lines of stone? ");
// TODO: Scan in the number of lines of blocks.
int linesOfStone;
scanf("%d", &linesOfStone);
printf("Enter lines of stone:\n");
// TODO: Scan in the lines of blocks.
int rowPos;
int columnPos;
int stoneLength;
int stoneValue;
int i = 0;
while (i < linesOfStone) {
scanf("%d %d %d %d", &rowPos, &columnPos, &stoneLength, &stoneValue);
if ( 0 <= rowPos && rowPos < SIZE &&
0 <= columnPos && columnPos < SIZE
&& columnPos + stoneLength - 1 < SIZE) {
int j = 0;
while (j < stoneLength) {
map[rowPos][columnPos + j] = STONE;
j++;
}
}
i++;
}
printMap(map, playerX);
// TODO: Scan in commands until EOF.
// After each command is processed, you should call printMap.
int quitLoop = 0;
int playerDirection = 0;
int playerMovement = 0;
while (quitLoop != 1) {
scanf("%d %d", &playerMovement, &playerDirection);
if ( playerMovement == 1 &&
playerDirection == 1 && playerX < (SIZE - 1)) {
//check player is within bounds
playerX++;
} else if ( playerMovement == 1 &&
playerDirection == -1 && playerX > 0 ) {
playerX--;
} else if ( playerMovement == 2) { // call function for destroying stones
destroyFallingStone (int map[][SIZE], int column);
}
printMap(map, playerX);
}
return 0;
}
// Print out the contents of the map array. Then print out the player line
// which will depends on the playerX variable.
void printMap(int map[SIZE][SIZE], int playerX) {
// Print values from the map array.
int i = 0;
while (i < SIZE) {
int j = 0;
while (j < SIZE) {
printf("%d ", map[i][j]);
j++;
}
printf("\n");
i++;
}
// Print the player line.
i = 0;
while (i < playerX) {
printf(" ");
i++;
}
printf("P\n");
}
//destroys the closes 2 stones
void destroyFallingStone (int map[][SIZE], int column) {
int i = 0;
int j = 0;
while (j < 3) {
while (i < 15 && map[i][column] != STONE) { //finding the first stone
i++;
}
// if there is a stone, destroy it
if (map[i][column] == STONE) {
map[i][column] = EMPTY;
}
i++;
}
}
You're not calling the function correctly:
} else if ( playerMovement == 2) { // call function for destroying stones
destroyFallingStone (int map[][SIZE], int column);
}
What you have here looks more like a declaration than a function call. You instead want:
} else if ( playerMovement == 2) { // call function for destroying stones
destroyFallingStone(map,column);
}
The problem is in line: 75 destroyFallingStone (int map[][SIZE], int column);. This should be a call to function destroyFallingStone. Something like destroyFallingStone (map, columnPos);.
Following is corrected code. See it compiling here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SIZE 15
#define EMPTY 0
#define STONE 1
// TODO: Add any extra #defines here.
// TODO: Add any extra function prototypes here.
void printMap(int map[SIZE][SIZE], int playerX);
void destroyFallingStone (int map[][SIZE], int column);
int main (void) {
// This line creates our 2D array called "map" and sets all
// of the blocks in the map to EMPTY.
int map[SIZE][SIZE] = {EMPTY};
// This line creates out playerX variable. The player starts in the
// middle of the map, at position 7.
int playerX = SIZE / 2;
printf("How many lines of stone? ");
// TODO: Scan in the number of lines of blocks.
int linesOfStone;
scanf("%d", &linesOfStone);
printf("Enter lines of stone:\n");
// TODO: Scan in the lines of blocks.
int rowPos;
int columnPos;
int stoneLength;
int stoneValue;
int i = 0;
while (i < linesOfStone) {
scanf("%d %d %d %d", &rowPos, &columnPos, &stoneLength, &stoneValue);
if ( 0 <= rowPos && rowPos < SIZE &&
0 <= columnPos && columnPos < SIZE
&& columnPos + stoneLength - 1 < SIZE) {
int j = 0;
while (j < stoneLength) {
map[rowPos][columnPos + j] = STONE;
j++;
}
}
i++;
}
printMap(map, playerX);
// TODO: Scan in commands until EOF.
// After each command is processed, you should call printMap.
int quitLoop = 0;
int playerDirection = 0;
int playerMovement = 0;
while (quitLoop != 1) {
scanf("%d %d", &playerMovement, &playerDirection);
if ( playerMovement == 1 &&
playerDirection == 1 && playerX < (SIZE - 1)) {
//check player is within bounds
playerX++;
} else if ( playerMovement == 1 &&
playerDirection == -1 && playerX > 0 ) {
playerX--;
} else if ( playerMovement == 2) { // call function for destroying stones
destroyFallingStone (map, columnPos);
}
printMap(map, playerX);
}
return 0;
}
// Print out the contents of the map array. Then print out the player line
// which will depends on the playerX variable.
void printMap(int map[SIZE][SIZE], int playerX) {
// Print values from the map array.
int i = 0;
while (i < SIZE) {
int j = 0;
while (j < SIZE) {
printf("%d ", map[i][j]);
j++;
}
printf("\n");
i++;
}
// Print the player line.
i = 0;
while (i < playerX) {
printf(" ");
i++;
}
printf("P\n");
}
//destroys the closes 2 stones
void destroyFallingStone (int map[][SIZE], int column) {
int i = 0;
int j = 0;
while (j < 3) {
while (i < 15 && map[i][column] != STONE) { //finding the first stone
i++;
}
// if there is a stone, destroy it
if (map[i][column] == STONE) {
map[i][column] = EMPTY;
}
i++;
}
}

Royal Flush not working for Card Hand Assignment [C]

I have tried everything! I'm supposed to add on the Royal Flush part. I understand the straight, flush, and straight flush part, but I cannot seem to get the Royal Flush part. In the end, the code is supposed to print how many straight, flushes, straight flushes, and royal flushes were in the deck of 50000 cards. This started out as a lab that I had with a partner, but now for extra credit, I'm supposed to add on the royal flush part and I'm clueless. Thanks in advance.
#include <stdio.h>
#define SIZE 50000
typedef struct card_t_struct{
int value; // 1 through 13
int suit; // 0 is clubes, 1 is diamonds, 2 is spades, 3 is hearts
} card_t;
void printCard(card_t card){
if(card.value == 1){
printf("Ace");
}else if(card.value == 11){
printf("Jack");
}else if(card.value == 12){
printf("Queen");
}else if(card.value == 13){
printf("King");
}else{
printf("%d", card.value);
}
printf(" of ");
if(card.suit == 0){
printf("Clubs.");
}else if(card.suit == 1){
printf("Diamonds.");
}else if(card.suit == 2){
printf("Spades.");
}else if(card.suit == 3){
printf("Hearts.");
}else{
printf("%d not a suit", card.suit); // Error message
}
printf("\n");
}
void hand(card_t* a){
int i = 0;
for(i = 0; i < 5; i++){
printCard(a[i]);
}
}
void shuffle(card_t* array, int length){
int i = 0;
for(i = 0; i < length * 2; i++){
int from = rand() % length;
int to = rand() % length;
card_t temp = array[from];
array[from] = array[to];
array[to] = temp;
}
}
void bubble(card_t* f, int length){
int i = 0;
int bub_num = 0;
for(bub_num = 0; bub_num < length; bub_num++){
for(i = 0; i < length - 1; i++){
if(f[i].value > f[i+1].value){ // Wrong order
int temp = f[i].value;
f[i].value = f[i+1].value;
f[i+1].value = temp;
}else{
}
}
}
}
int isFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int isStraight(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i+1].value != deck[i].value + 1){
return 0;
}
}
return 1;
}
int isSFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i+1].value != deck[i].value + 1){
return 0;
}
}
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int isRFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i].value != deck[i].value){
return 0;
}
}
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int main(){
srand(time(0));
card_t deck[52] = {};
int i = 0;
int flush = 0;
int straight = 0;
int straight_flush = 0;
int royal_flush = 0;
int suit = 0;
for(suit = 0; suit < 4; suit++){
int value = 1;
for(value = 1; value <= 13; value++){
deck[i].suit = suit;
deck[i].value = value;
i++;
}
}
for(i = 0; i < SIZE; i++){
shuffle(deck, 52);
hand(deck);
if(isFlush(deck) ){
flush++;
}
printf("\n");
bubble(deck, 5);
if(isStraight(deck) ){
straight++;
}
if(isSFlush(deck) ){
straight_flush++;
}
if(isRFlush(deck) ){
royal_flush++;
}
}
printf("The number of flushes you have is: %d\n", flush);
printf("The number of straights you have is: %d\n", straight);
printf("The number of straight flushes you have is: %d\n", straight_flush);
printf("The number of royal flushes you have is: %d\n", royal_flush);
}
Based on the existing IsStraight(...) function, I'm assuming that your isRFlush(...) functions are being passed a five-card hand (not an entire deck) whose cards are in ascending order?
int isRFlush(card_t* deck) {
int i = 0; // zero-based index into your hand of five cards (0-4)
// This next bit DOESN'T ACTUALLY DO ANYTHING. The reason is that comparing anything
// with itself will always result in an equality (i.e. 1==1, 3.14==3.14, a==a, etc),
// so this comparison always returns false, and the return 0 after the if statement
// is never taken, regardless of the value of the cards passed in.
/*
for (i = 1; i < 5; i++) {
if (deck[i].value != deck[i].value) { // <--- Never false, no matter what
return 0;
}
}
*/
// What the other isXxxx methods above were doing was ensuring that each 'next' card
// was 'one higher' than the card that came before it in the hand. If that's found to
// be untrue for any card in the hand, then the function exits with a zero.
//
// That's the logic for a STRAIGHT, but we're looking for a ROYAL STRAIGHT, so the
// hand HAS to be "10 J Q K A" (all of the same suit, but we'll check that part later).
//
// Since the Ace represents a non-sequential value, I think you may as well just do
// this using five comparisons without the loop:
if ( deck[0].value != 1 // if 1st card isn't Ace
|| deck[1].value != 10 // or 2nd card isn't 10
|| deck[2].value != 11 // or 3rd card isn't Jack
|| deck[3].value != 12 // or 4th card isn't Queen
|| deck[4].value != 13) { // or 5th card isn't King
return 0; // Not a royal straight
}
// If we've made it this far, we know that we have a ROYAL STRAIGHT (e.g. 10, J, Q, K, A)
// Now, we need to ensure that we also have a FLUSH
// Loop through the 2nd to last cards, ensuring they are all
// of the same suit as the first card in the hand
for (i = 1; i < 5; i++) {
if (deck[i].suit != deck[0].suit) {
return 0; // Not a flush
}
}
return 1; // This hand IS a Royal Straight Flush (aka Royal Flush)
}
Final notes:
There may be other bugs in this program. For example, isStraight(...) skips the first card and loops over the last four cards, but it's ADDING ONE to the index i when it should be SUBTRACTING ONE:
// Note: This function doesn't recognize a non-sequential "ace-high" flush
// (e.g. 10,J,Q,K,A).
int isStraight(card_t* deck) {
int i = 0;
for (i = 1; i < 5; i++) {
// Loop values of i will be [1, 2, 3, 4], which correspond to the 2nd through 5th card in the hand passed in.
// To check these against the previous card, you should subtract one (vs adding one).
/*
if (deck[i+1].value != deck[i].value + 1) { // <--- Array Index Out Of Bounds
*/
// If card in hand isn't 'one higher' than the previous card...
if (deck[i-1].value != deck[i].value + 1) {
return 0;
}
}
return 1;
}
Since you already have a function that checks a hand for flush, you could leverage that to save some typing by calling it in your isRFlush(...) function:
int isRFlush(card_t* deck) {
if ( deck[0].value != 1 // if 1st card isn't Ace
|| deck[1].value != 10 // or 2nd card isn't 10
|| deck[2].value != 11 // or 3rd card isn't Jack
|| deck[3].value != 12 // or 4th card isn't Queen
|| deck[4].value != 13) { // or 5th card isn't King
return 0; // Not a royal straight
}
// At this point, you know it's a ROYAL STRAIGHT, so just return whether or not it's also
// a FLUSH
return isFlush(deck);
}

Trouble with pset3 game of fifteen

My functions (init,draw,move and win) are not working properly. Can anyone shed some light on where I am going wrong?
init - should initialer the board and swap 1 and 2.
draw - should draw the current state of the board.
move - should move the tile if not illegal move.
win - should check the board if its in descending order.
/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#
define _XOPEN_SOURCE 500
# include < cs50.h > #include < stdio.h > #include < string.h > #include <
stdlib.h > #include < unistd.h >
// constants
#define DIM_MIN 3# define DIM_MAX 9
// board
int board[DIM_MAX][DIM_MAX];
// dimensions
int d;
// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
void metrytoexchange(int * a, int * b);
int main(int argc, string argv[]) {
// ensure proper usage
if (argc != 2) {
printf("Usage: fifteen d\n");
return 1;
}
// ensure valid dimensions
d = atoi(argv[1]);
if (d < DIM_MIN || d > DIM_MAX) {
printf("Board must be between %i x %i and %i x %i, inclusive.\n",
DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
return 2;
}
// open log
FILE * file = fopen("log.txt", "w");
if (file == NULL) {
return 3;
}
// greet user with instructions
greet();
// initialize the board
init();
// accept moves until game is won
while (true) {
// clear the screen
clear();
// draw the current state of the board
draw();
// log the current state of the board (for testing)
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
fprintf(file, "%i", board[i][j]);
if (j < d - 1) {
fprintf(file, "|");
}
}
fprintf(file, "\n");
}
fflush(file);
// check for win
if (won()) {
printf("ftw!\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = GetInt();
// quit if user inputs 0 (for testing)
if (tile == 0) {
break;
}
// log move (for testing)
fprintf(file, "%i\n", tile);
fflush(file);
// move if possible, else report illegality
if (!move(tile)) {
printf("\nIllegal move.\n");
usleep(500000);
}
// sleep thread for animation's sake
usleep(500000);
}
// close log
fclose(file);
// success
return 0;
}
/**
* Clears screen using ANSI escape sequences.
*/
void clear(void) {
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
/**
* Greets player.
*/
void greet(void) {
clear();
printf("WELCOME TO GAME OF FIFTEEN\n");
usleep(2000000);
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).
*/
void init(void) {
// TODO
int i, j;
int k = d * d - 1;
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) {
board[i][j] = k--;
if (k % 2 != 0) {
break;
} else {
if ((board[i][j] == 2) && (board[i][j - 1] == 1))
metrytoexchange( & board[i][j], & board[i][j - 1]);
}
}
}
}
/**
* Prints the board in its current state.
*/
void draw(void) { // TODO
int k = d * d - 1;
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
board[i][j] = k--;
if (board[i][j] == 0) {
printf("_");
} else
printf("%d \t", board[i][j]);
}
printf("\n");
}
}
void metrytoexchange(int * a, int * b) {
int temp = * a; *
a = * b; *
b = temp;
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile) {
int k = d * d - 1;
int blank_space = 0;
//dont go beyond the grid
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (tile < k && tile > 0 && tile == board[i][j]) {
continue;
} else {
break;
}
//iterate to check the position of of blank tile;left to right up and down if not return false
if (board[i - 1][j] != blank_space || board[i][j - 1] !=
blank_space || board[i + 1][j] != blank_space || board[i][j +
1
] != blank_space) {
return false;
}
//else swap tile with blank_space
else {
metrytoexchange( & tile, & blank_space);
return true;
}
}
}
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(void) {
// TODO
// creat a variable that increases as the loop condition increases.let it start from 1 increasing
int win_board[d][d];
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (win_board[i][j] == board[i][j]) {
return true;
} else {
return false;
}
}
}
return false;
}

Why is array[i][-1] == 0? How does one prevent undefined variables from being used? [duplicate]

This question already has answers here:
Are negative array indexes allowed in C?
(9 answers)
Closed 6 years ago.
/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#define _XOPEN_SOURCE 500
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// constants
#define DIM_MIN 3
#define DIM_MAX 9
// board
int board[DIM_MAX][DIM_MAX];
int b;
// dimensions
int d;
// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
int main(int argc, string argv[])
{
// ensure proper usage
if (argc != 2)
{
printf("Usage: fifteen d\n");
return 1;
}
// ensure valid dimensions
d = atoi(argv[1]);
if (d < DIM_MIN || d > DIM_MAX)
{
printf("Board must be between %i x %i and %i x %i, inclusive.\n",
DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
return 2;
}
// open log
FILE* file = fopen("log.txt", "w");
if (file == NULL)
{
return 3;
}
// greet user with instructions
greet();
// initialize the board
init();
// accept moves until game is won
while (true)
{
// clear the screen
clear();
// draw the current state of the board
draw();
// log the current state of the board (for testing)
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
fprintf(file, "%i", board[i][j]);
if (j < d - 1)
{
fprintf(file, "|");
}
}
fprintf(file, "\n");
}
fflush(file);
// check for win
if (won())
{
printf("ftw!\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = GetInt();
// quit if user inputs 0 (for testing)
if (tile == 0)
{
break;
}
// log move (for testing)
fprintf(file, "%i\n", tile);
fflush(file);
// move if possible, else report illegality
if (!move(tile))
{
printf("\nIllegal move.\n");
usleep(500000);
}
// sleep thread for animation's sake
usleep(500000);
}
// close log
fclose(file);
// success
return 0;
}
/**
* Clears screen using ANSI escape sequences.
*/
void clear(void)
{
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
/**
* Greets player.
*/
void greet(void)
{
clear();
printf("WELCOME TO GAME OF FIFTEEN\n");
usleep(2000000);
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).
*/
void init(void)
{
for(int i = 0, j = 0, k = ((d*d)-1); i < d; j++, k--)
{
if(j == d)
{
i = i + 1;
j = 0;
}
board[i][j] = k;
}
if((d*d)%2 == 0)
{
board[(d-1)][(d-2)] = 2;
board[(d-1)][(d-3)] = 1;
}
board[(d-1)][(d-1)] = 0;
b = board[(d-1)][(d-1)];
}
/**
* Prints the board in its current state.
*/
void draw(void)
{
for(int i = 0, j = 0; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
printf("\n");
}
if(board[i][j] == 0) //b used to be 99
{
printf(" _");
}
else
{
printf(" %2d", board[i][j]);
}
}
printf("\n");
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile)
{
//find tile
for(int i = 0, j = 0; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
}
if (board[i][j] == tile)
{
//check if tile position is in valid perimeter of blank space
if (board[i+1][j] == b)
{
board[i+1][j] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i-1][j] == b)
{
board[i-1][j] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i][j+1] == b)
{
board[i][j+1] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i][j-1] == b)
{
printf("%i", board[i][j-1]);
board[i][j-1] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
}
}
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(void)
{
for(int i = 0, j = 0, k = 1; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
}
if (k == (d*d)-1)
{
return true;
}
if (board[i][j] == k)
{
k = k + 1;
}
}
return false;
}
I originally had
board[(d-1)][(d-1)] = 0;
equal to 99 along with the move function look for 99. For my problem set I was supposed to use 0. Once I changed 99 to 0, for some reason 0 is being found if board[i][j-1] even if that means board[2][-1]. Why is that allow/why does that equal 0? and how can I disable this?
You have int board[DIM_MAX][DIM_MAX]; where #define DIM_MIN 3 and the memory allocated for elements are contiguous, so typically you will access board[1][2] by using board[2][-1]. But this is undefined behavior, which allows anything to happen, and you mustn't use that.
Quote from N1570 J.2 Undefined behavior:
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
board[2][-1]. Why is that allow
C does allow you access out of range of an array. But it is Undefined Behavior.
why does that equal 0?
By accident. It's Undefined Behavior and it could be anything.

Resources