Home > database >  How can I reference arrays with different numbers in their name in Bash?
How can I reference arrays with different numbers in their name in Bash?

Time:06-29

(Apologies in advance if my english is bad)

So, I have started studying bash, and want to make a Connect 4 game in it. However, I got stuck a bit. I have 7 arrays named column0 to column6, and I want to reference them later on.

I read in another post a few days ago, that i can use nameref to do so, but I think I'm doing something wrong, as the function runs, but doesn't do anything (doesn't check for winner). Here is a snippet form the code

declare -n nr="column$j"
for ((j=0 ; j < 6; j   )); do
    if [ "${nr[0]}" = $k ] && [ "${nr[1]}" = $k ] && [ "${nr[2]}" = $k ] && [ "${nr[3]}" = $k ]; then

(this is part of the function that will check for a winner, in case 4 characters in a row match. 'k' is just a color variable, it can be $k='Y' or $k='R')

Could someone point out what I'm doing wrong here? Or am I just dumb and Bash can't work with such solutions? Thank you in advance for any help.

CodePudding user response:

Given your specifications I tried to reproduce a minimal example.
You can try to do something like this:

#!/usr/bin/env bash

k="Y"

nr_0=("R" "R" "Y" "Y")
nr_1=("R" "Y" "Y" "Y")
nr_2=("Y" "R" "Y" "Y")
nr_3=("Y" "Y" "R" "Y")
nr_4=("Y" "Y" "Y" "R")
nr_5=("Y" "Y" "Y" "Y") # the winner
nr_6=("Y" "R" "Y" "Y")

for j in {0..6}; do
    tmp_array_name="nr_$j[@]"
    tmp_array=("${!tmp_array_name}")

    if [ "${tmp_array[0]}" == "$k" ] && [ "${tmp_array[1]}" == "$k" ] && [ "${tmp_array[2]}" == "$k" ] && [ "${tmp_array[3]}" == "$k" ]; then
        echo "The winner is $tmp_array_name - ${tmp_array[*]}"
    fi
done

With this output:
The winner is nr_5[@] - Y Y Y Y

CodePudding user response:

You need the nameref declare assignment to be within your loop or it gets assigned an empty string:

for ((j=0 ; j < 6; j   )); do
  declare -n nr="column$j"
  if [ "${nr[0]}" = $k ] && [ "${nr[1]}" = $k ] && [ "${nr[2]}" = $k ] && [ "${nr[3]}" = $k ]; then

Another option to nameref which is as risky as the dynamic naming ${!dyn_name_var}, is to use Bash's associative arrays:

declare -A grid=()
for ((column=0 ; j < 6; column   )); do
  if [ "${grid[$column,0]}" == "$k" ] &&
     [ "${grid[$column,1]}" == "$k" ] &&
     [ "${grid[$column,2]}" == "$k" ] &&
     [ "${grid[$column,3]}" == "$k" ]
  then
    : ...
  fi
  : ...
done

This will use an associative arrays of key formed by column,line. Example of the first two lines of the grid associative array as declared statically.

declare -A grid=(
  [0,0]="o" [0,1]="x" [0,2]=" ", [0,3]="o"
  [1,0]=" " [1,1]="o" [1,2]="x", [1,3]="o"
)

See: How to declare 2D array in bash

  •  Tags:  
  • bash
  • Related