Program that moves the knight on the chessboard - c

This program changes the position of a chessboard from 0 to 1 when the knight moves from one position to another. If I try the case 0 the program works. Then after the case 0 if I try the case 1 the position changed to 1 is the one that is placed up-left from the case 0 one. Instead it should be the one placed up-up-right from the case 0 one. Why is the output like this?
#include <stdio.h>
int main(){
int board[8][8]={0};
int currentRow=4, currentColumn=4;
int cont=0, moveNumber=0, i, j;
while(moveNumber>=0 && moveNumber<=7){
printf("Enter a move: ");
scanf("%d", &moveNumber);
cont++;
switch(moveNumber){
case 0:
board[currentRow-1][currentColumn+2]=1;
break;
case 1:
board[currentRow-2][currentColumn+1]=1;
break;
case 2:
board[currentRow-2][currentColumn-1]=1;
break;
case 3:
board[currentRow-1][currentColumn-2]=1;
break;
case 4:
board[currentRow+1][currentColumn-2]=1;
break;
case 5:
board[currentRow+2][currentColumn-1]=1;
break;
case 6:
board[currentRow+2][currentColumn+1]=1;
break;
case 7:
board[currentRow+1][currentColumn+2]=1;
break;
}
for(i=0; i<8; i++){
for(j=0; j<8; j++){
printf("%d ", board[i][j]);
}
printf("\n");
}
printf("Total moves: %d\n",cont);
}
return 0;
}

The main issue is that you never update currentRow or currentColumn, so all moves happen from their initial values.
Some other notes: You should avoid "magic numbers" - 8 in this case. If you decide to change the size of the array, you have to search through all the code and find the eights and replace them. Use a define or const int.
You should always check the return value from scanf. What if the user types a, for example?
Array bounds checking is needed. What happens when a move takes the knight off the board - and past the bounds of the array?
#include <stdio.h>
// Avoid magic numbers
#define ROWS 8
#define COLS 8
int main(){
int board[ROWS][COLS] = {0};
int currentRow = 4, currentColumn = 4;
int cont = 0, moveNumber = 0, i, j;
// Loop forever
while (1) {
printf("Enter a move: ");
// Make sure user enters a number
while (1 != scanf("%d", &moveNumber)) {
// clear stdin
int c;
while((c = getchar()) != '\n' && c != EOF);
// See https://stackoverflow.com/a/6277391/669576
// for why fgets/sscanf is a better option than scanf
// Prompt user for new input
printf("Enter a valid integer:");
}
// Moved this here
if (moveNumber < 0 || moveNumber > 7) break;
cont++;
// Going to use some temp vars to calculate indices
int tempRow, tempCol;
// Calc new indices
switch (moveNumber) {
case 0:
tempRow = currentRow - 1;
tempCol = currentColumn + 2;
break;
case 1:
tempRow = currentRow - 2;
tempCol = currentColumn + 1;
break;
case 2:
tempRow = currentRow - 2;
tempCol = currentColumn - 1;
break;
case 3:
tempRow = currentRow - 1;
tempCol = currentColumn - 2;
break;
case 4:
tempRow = currentRow + 1;
tempCol = currentColumn - 2;
break;
case 5:
tempRow = currentRow + 2;
tempCol = currentColumn - 1;
break;
case 6:
tempRow = currentRow + 2;
tempCol = currentColumn + 1;
break;
case 7:
tempRow = currentRow + 1;
tempCol = currentColumn + 2;
break;
}
// Make sure we have valid indices
if (tempRow < 0 || tempCol < 0 || tempRow >= ROWS || tempCol >= COLS) {
printf("Illegal move\n");
}
else {
// Update the board
currentRow = tempRow;
currentColumn = tempCol;
board[currentRow][currentColumn] = 1;
// And print
for(i = 0; i < ROWS; i++){
for(j = 0; j < COLS; j++){
printf("%d ", board[i][j]);
}
printf("\n");
}
printf("Total moves: %d\n", cont);
}
}
return 0;
}

As #Jonhnny Mopp pointed out, you never update currentRow or currentColumn.
So after case 0 you set board[3][6] and after case 1 you set board[2][5].
So the return of case 1 is up-left of case 0.

I recommend you write a function TryToMoveKnight(int* x, int* y, int moveNumber) that attempts to move a knight in the desired direction.
You already have eight lines of very similar code, and the more work you need to do to move the piece, the worse it's going to get.
Things the function needs to do:
determine the target coordinates from the moveNumber and current
position
verify that the target coordinates are on the board
possibly check for a piece at that position
assign the new coordinates to your variables x and y whose addresses you passed in
This last step was missing from your original code, but checking that the target position is on the board is also going to be essential.
So where you currently have switch(moveNumber)... you would instead call TryToMoveKnight(&currentRow,&currentColumn,moveNumber);

Related

Switch statement with two arguments

I have a question related to switch statement with 2 arguments. I do not understand which value to look for. I've read somewhere that comma(,) is equal to AND,but that is not helping me much since when debugging it goes to case 1,case 1,and then default,so I really don't get it.
Any help would be appreaciated,Thanks!
#define ADD(x, y) x+y
#define MUL(x, y) x*y
void main() {
int arr[6] = { 012, -2, 7 - 011, 0x1F, 3 }, res = 0;
int n = sizeof(arr) / sizeof(int), i, j;
for (i = -1, j = n; i <= n / 2;) {
switch (--j, ++i) {
case 0: res += MUL(arr[i], arr[j]);
case 1: res += ADD(arr[i], arr[j]); break;
case 4: res += MUL(ADD(arr[i], arr[j]), ADD(arr[i + 1], res));
default: res++; break;
}
}
printf("%d", res);
} ```
Operator comma is not equal to AND. Operator comma evaluates operands from left to right, and returns the last result. Thus,
switch (--j, ++i) {
i = 0;
it goes to the case 0, you don`t have break statement so you go to the case 1

C language switch-case: avoiding a case after used once

I'm trying a challenge where I need to get a random number, and print the sum of the digits inside the number without duplicates:
for example, 123 will print 6 ( 1 + 2 + 3 ), and 32111 will do the same ( because we don't add duplicates to our sum, the sum of this number is similar to the sum of 123. )
In my solution I thought about using switch case for each number, and use a flag that its value is one, than in each case I add 1 to the flag, and when the flag is 2 I add the number to the sum, but I don't know how to avoid a case after it happend, which if I see it correctly will avoid me using multiple flags for each number (because if we could avoid a case after it happend, i just could set the flag back to one after the switch and do all the process again )
can you help me out? thanks a lot!
#include <stdio.h>
#define TEN 10
#define NINE 9
#define EIGHT 8
#define SEVEN 7
#define SIX 6
#define FIVE 5
#define FOUR 4
#define THREE 3
#define TWO 2
#define ONE 1
int main(void)
{
int answer = 0, i = 0, remain = 0, sum = 0, flag = 1;
printf("Enter a number: ");
scanf("%d", &answer);
while(answer >= ONE)
{
remain = answer % TEN;
answer /= TEN;
printf("%d\n", remain);
switch (remain)
{
case ONE:
{
flag++;
if (flag == TWO)
{
sum = sum + ONE;
}
break;
}
case TWO:
{
flag++;
if (flag == TWO)
{
sum = sum + TWO;
}
break;
}
case THREE:
{
flag++;
if (flag == TWO)
{
sum = sum + THREE;
}
break;
}
case FOUR:
{
flag++;
if (flag == TWO)
{
sum = sum + FOUR;
}
break;
}
case FIVE:
{
flag++;
if (flag == TWO)
{
sum = sum + FIVE;
}
break;
}
case SIX:
{
flag++;
if (flag == TWO)
{
sum = sum + SIX;
}
break;
}
case SEVEN:
{
flag++;
if (flag == TWO)
{
sum = sum + SEVEN;
}
break;
}
case EIGHT:
{
flag++;
if (flag == TWO)
{
sum = sum + EIGHT;
}
break;
}
case NINE:
{
flag++;
if (flag == TWO)
{
sum = sum + NINE;
}
break;
}
default:
{
}
}
}
printf("The sum of the number is: %d", sum);
return 0;
}
Try using a bitmask representing each case. The main idea is to keep track for each number (from 0 to 9) using only one integer. Some bit of this single integer can be used as to find whether this number was seen before or not. If the bit is 0 then the corresponding number is seen for the first time (and we now set the bit to 1), and if we see that the bit is already 1, then we don't add it into our final sum.
int mask = 0;
switch (remain) {
case 1: // 001
if ((mask & 1) == 0) { // 1 = 1 << 0
sum += 1;
mask |= 1;
}
break;
...
case 3: // 100
if ((mask & 4) == 0) { // 4 = 1 << 2
sum += 3;
mask |= 4;
}
break;
...
case n:
if ((mask & k) == 0) { // k = 1 << (n-1)
sum += n;
mask |= k;
}
break;
...
Now you can see a pattern in the last case I used, we can simplify this switch-case into a single if statement.
int mask = 0;
int sum = 0;
while (answer) {
remain = answer % 10;
answer /= 10;
int offset = remain;
int flag = 1 << offset;
if ((mask & flag) == 0) {
sum += remain;
mask |= flag;
}
}
// sum contains the required answer
Each bit represents one of the cases, since you have only 10 cases this is the most efficient way to track the flags as you have more than 10 bits for an integer and it will be wastage to have a separate boolean flag for 0 to 9.
A case-term is a compile time constant, so you cannot "disable" it at runtime at the c language level. You would have to introduce a separate flag for each digit then.
I'd say - and have a look at you code - the switch-case approach is not the best as you duplicate a lot of similar code. A much easier way would be to have an array of 10 ints, each standing for a particular digit, and once a digit is encountered, set the respective array element to 1. At the end sum up in a loop.
If you have troubles getting this approach running, don't hesitate to ask again...

Counting vowels in text without arrays (C)

i have to write a program that counts all vowels in a text & gives out the percentage of every vowel for the whole text.
For whatever reason we are not allowed to use arrays, but instead should do it with getchar().
#include <stdio.h>
#include <ctype.h>
int main() {
int current;
int cntAll = 0;
int cntA = 0, cntE = 0, cntI = 0, cntO = 0, cntU = 0;
int pA = 0, pE = 0, pI = 0, pO = 0, pU = 0;
printf("Enter Text: ");
while ((current = getchar()) != EOF){
if (isspace(current)) continue; // check for whitespace, if whitespace continue
else {
switch (current) { // check for vowel & increase vowelcount
case 'a':
cntA += 1;
case 'A':
cntA += 1;
case 'e':
cntE += 1;
case 'E':
cntE += 1;
case 'i':
cntI += 1;
case 'I':
cntI += 1;
case 'o':
cntO += 1;
case 'O':
cntO += 1;
case 'u':
cntU += 1;
case 'U':
cntU += 1;
}
}
cntAll++;
}
pA = (cntA / cntAll) * 100;
pE = (cntE / cntAll) * 100;
pI = (cntI / cntAll) * 100;
pO = (cntO / cntAll) * 100;
pU = (cntU / cntAll) * 100;
printf("\nLetters: %d\nPercentage A: %d\nPercentage E: %d\nPercentage I: %d\nPercentage O: %d\nPercentage U: %d\n",cntAll,pA,pE,pI,pO,pU);
system("PAUSE");
return 0;
}
Increasing the cntAll value works without problems, but it doesn't count the individual vowels for whatever reason.
Would appreciate any help!
Edited:
#include <stdio.h>
#include <ctype.h>
int main() {
int current;
int cntAll = 0;
int cntA = 0, cntE = 0, cntI = 0, cntO = 0, cntU = 0;
double pA = 0, pE = 0, pI = 0, pO = 0, pU = 0;
printf("Enter Text: ");
while ((current = getchar()) != EOF){
if (isspace(current)) continue;
else {
switch (current) {
case 'a':case 'A':
cntA += 1;
break;
case 'e':case 'E':
cntE += 1;
break;
case 'i':case 'I':
cntI += 1;
break;
case 'o':case 'O':
cntO += 1;
break;
case 'u':case 'U':
cntU += 1;
break;
}
}
cntAll++;
}
pA = 100.0 * cntA / cntAll;
pE = 100.0 * cntE / cntAll;
pI = 100.0 * cntI / cntAll;
pO = 100.0 * cntO / cntAll;
pU = 100.0 * cntU / cntAll;
printf("\nLetters: %d\nPercentage A: %.2lf\nPercentage E: %.2lf\nPercentage I: %.2lf\nPercentage O: %.2lf\nPercentage U: %.2lf\n",cntAll,pA,pE,pI,pO,pU);
system("PAUSE");
return 0;
}
cheers
You need to insert break statements between the cases.
Otherwise the program will execute all the statements below the one first entered. Actually this is a good feature. It allows you to consider multiple labels at the same time. Putting this together you get:
switch (current){
case 'a': case 'A':
cntA += 1;
break; // Don't follow through to the other cases.
case 'b': case 'B': /*etc*/
After this, note that (cntA / cntAll) * 100; will evaluate the expression in parentheses in integer arithmetic, which will truncate it to 0 in most cases. The fix is to write it as
100 * cntA / cntAll;
This will still truncate to an integer. If that's not tolerable then consider using the floating point expression 100.0 * cntA / cntAll and change your printf formatters accordingly. Using floating point is arguably better anyway as it obviates the potential for overflow when evaluating 100 * cntA.
case labels falls through to the next one below it without a break.
So if you read an 'a' then all the cases in your switch will be executed.
You need something like
switch (current) { // check for vowel & increase vowelcount
case 'a':
cntA += 1;
break; // <-- Note break here
...
First thing i notice is that you are missing break on every switch case. This will lead to wrong behaviour.
Second thing:
pA = (cntA / cntAll) * 100;
will calculate cntS/cntAll first which is <0. This value will be interpreted as integer so you always have 0*100 which is 0. You can rewrite it as
pA = (cntA * 100 ) / cntAll;
In that case you don't have to cast to float to get the right result. Note that for large cntA you may overflow.

Switch/String in c

I am trying to get this function to return a string.
char * vergleich(int random) {
char *erg;
switch(random) {
case 1: erg = "Siccor" ; break;
case 2: erg = "Paper" ; break;
case 3: erg = "Rock" ; break;
case 4: erg = "Lizard" ; break;
case 5: erg = "Spock" ; break;
default: break;
return erg;
}
}
int main() {
srand(time(NULL));
int p1 = rand() % 4;
int p2 = rand() % 4;
printf("player1 shows %s\n", vergleich(p1));
printf("\n\tif Player 2 plays %s or %s Player1 wins\n", vergleich(p1+1), vergleich(p1+3));
if(p2 == p1 + 1 || p2 == p1 +3) {
printf("player1 wins");
}else {printf("player2 wins");}
return 0;
}
}
I think the initialisation of the function is wrong, but I dont really know how to deal with strings, please help.
If I run the program it just crashes if case > 2. and the strings are not displayed right.
The crash happens since the function vergleich() can be called with argument 0 (when p1 is 0) and 6 when p1 is 3. Zero and six are not handled in the switch, so pointer erg points to junk.
So, I suggest to enumerate your items starting from 0 to 4. To avoid overflow during additions you should also use modulo operation %, for example (p1 + 3) % 5, (p1 + 1) % 5.
To generate random from 0 to 4 you can use rand() % 5;.

Find numbers of subarray of an array whose sum is divided by 3

I got stuck in one algorithm question. Please suggest me some efficient algorithm for the below problem
Question is
Find numbers of subarrays(in range between 0 < R < N) whose sum is divisible by given number.
My approach:
Input: 0 5 3 8 2 1
Sum: 0 0 5 8 16 18 19
Mod 3: 0 0 2 2 1 0 1
No. of ways to chooses 0 , 1 or 2 is NC2
Problem: Is i am have asked to choose between some range i.e from 2 to 5 so array will become:
3 8 2 1
Does I have to recalculate the sum and Mod again or the original MOd array will give me a correct answerSecond Problem: What IF i change one element i.e 8 is change to 11 , How it will be effectFor the above problem I am considering using BIT dp[4][Max. Element] if mod is 0 update dp[0] if 1 update dp[1] so on How To update if VAlue at index is change
check this out:
this subroutine findes the largest subarray which its sum divided by 3.
It goes only once over at the array with no extra space.
here c++ code:
int largest_3_divider_subarray(int* a, int len){
int cum_sum = 0;
int index_of_first_one = -1;
int index_of_first_two = -1;
int absolute_maximal = 0;
int current_maximal = 0;
bool flag1 = 1, flag2 = 1;
for(int i = 0; i < len; ++i){
cum_sum += a[i];
switch (cum_sum%3)
{
case 1:
if(flag1){
index_of_first_one = i;
flag1 = 0;
}else
current_maximal = i - index_of_first_one;
break;
case 2:
if(flag2){
index_of_first_two = i;
flag2 = 0;
}else
current_maximal = i - index_of_first_two;
break;
case 0:
current_maximal = i;
}
if(current_maximal > absolute_maximal)
absolute_maximal = current_maximal;
}
return absolute_maximal + 1;
}
int main()
{
int A[]= {6,8,-2,0,9,13,1};
int k = largest_3_divider_subarray(A,7);
return 0;
}
It could be a running contest problem however there's a dp approach for that. you need to combine it with segment tree if you want to solve the running contest problem.
the basic idea:
take care of %3 value of the sum of the digits of the substrings/subarrays which end at the current character/digit.
Then take it as a subproblem and try to get the number of subarrays which end at the next character/digit with different mod values using the previously obtained data.
(characteristics of dp: we try to solve a subproblem then using the values obtained we try to solve a subproblem of bigger instance).
You just have to combine with segment trees if you want to solve the running contest problem in codechef
There are some good tutorials available for segment tree
public static int largest_3_divider_subarray(int a[]){
int cum_sum = 0;
int index_of_first_one = -1;
int index_of_first_two = -1;
int absolute_maximal = 0;
int current_maximal = 0;
boolean flag1 = true, flag2 = true;
for(int i = 0; i < a.length; ++i){
cum_sum += a[i];
switch ((cum_sum%3))
{
case 1:
case -2:
if(flag1){
index_of_first_one = i;
flag1 = false;
}else
current_maximal = i - index_of_first_one;
break;
case 2:
case -1:
if(flag2){
index_of_first_two = i;
flag2 = false;
}else
current_maximal = i - index_of_first_two;
break;
case 0:
current_maximal = i+1;
}
if(current_maximal > absolute_maximal)
absolute_maximal = current_maximal;
}
return absolute_maximal ;
}

Resources