I am working on a larger project to write a code so the user can play Connect 4 against the computer. Right now, the user can choose whether or not to go first and the board is drawn. While truing to make sure that the user can only enter legal moves, I have run into a problem where my function legal_moves() takes 1 positional argument, and 0 are given, but I do not understand what I need to do to male everything agree.
#connect 4
#using my own formating
import random
#define global variables
X = "X"
O = "O"
EMPTY = "_"
TIE = "TIE"
NUM_ROWS = 6
NUM_COLS = 8
def display_instruct():
"""Display game instructions."""
print(
"""
Welcome to the second greatest intellectual challenge of all time: Connect4.
This will be a showdown between your human brain and my silicon processor.
You will make your move known by entering a column number, 1 - 7. Your move
(if that column isn't already filled) will move to the lowest available position.
Prepare yourself, human. May the Schwartz be with you! \n
"""
)
def ask_yes_no(question):
"""Ask a yes or no question."""
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question,low,high):
"""Ask for a number within range."""
#using range in Python sense-i.e., to ask for
#a number between 1 and 7, call ask_number with low=1, high=8
low=1
high=NUM_COLS
response = None
while response not in range (low,high):
response=int(input(question))
return response
def pieces():
"""Determine if player or computer goes first."""
go_first = ask_yes_no("Do you require the first move? (y/n): ")
if go_first == "y":
print("\nThen take the first move. You will need it.")
human = X
computer = O
else:
print("\nYour bravery will be your undoing... I will go first.")
computer = X
human = O
return computer, human
def new_board():
board = []
for x in range (NUM_COLS):
board.append([" "]*NUM_ROWS)
return board
def display_board(board):
"""Display game board on screen."""
for r in range(NUM_ROWS):
print_row(board,r)
print("\n")
def print_row(board, num):
"""Print specified row from current board"""
this_row = board[num]
print("\n\t| ", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num],"|")
print("\t", "|---|---|---|---|---|---|---|")
# everything works up to here!
def legal_moves(board):
"""Create list of column numbers where a player can drop piece"""
legals = []
if move < NUM_COLS: # make sure this is a legal column
for r in range(NUM_ROWS):
legals.append(board[move])
return legals #returns a list of legal columns
#in human_move function, move input must be in legal_moves list
print (legals)
def human_move(board,human):
"""Get human move"""
legals = legal_moves(board)
print("LEGALS:", legals)
move = None
while move not in legals:
move = ask_number("Which column will you move to? (1-7):", 1, NUM_COLS)
if move not in legals:
print("\nThat column is already full, nerdling. Choose another.\n")
print("Human moving to column", move)
return move #return the column number chosen by user
def get_move_row(turn,move):
move=ask_number("Which column would you like to drop a piece?")
for m in range (NUM_COLS):
place_piece(turn,move)
display_board()
def place_piece(turn,move):
if this_row[m[move]]==" ":
this_row.append[m[move]]=turn
display_instruct()
computer,human=pieces()
board=new_board()
display_board(board)
move= int(input("Move?"))
legal_moves()
print ("Human:", human, "\nComputer:", computer)
Right down the bottom of the script, you call:
move= int(input("Move?"))
legal_moves()
# ^ no arguments
This does not supply the necessary board argument, hence the error message.
Related
Code:
local DataStoreService = game:GetService("DataStoreService")
local InvDataStore = DataStoreService:GetDataStore("InvDataStore")
game.Players.PlayerAdded:Connect(function(player)
local Id = player.UserId
local Inventory = Instance.new("Folder")
Inventory.Name = "Inventory"
Inventory.Parent = player
local Inv = InvDataStore:GetAsync(Id)
print(Inv)
print(table.concat(Inv, " "))
end)
game.Players.PlayerRemoving:Connect(function(player)
local Id = player.UserId
local InvTable = {}
for i, v in pairs(game.Players:FindFirstChild(player.Name).Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
print(InvTable)
print(table.concat(InvTable, " "))
InvDataStore:SetAsync(Id, InvTable)
end)
Output:
13:25:35.288 - Untitled Game auto-recovery file was created
Realism Mod is currently running v2.09! (x2)
table: 0x08cb53598b2d3aa1
table: 0xd8ce847b521d4091
1
13:26:26.703 - Disconnect from ::ffff:127.0.0.1|60556
Explorer:
It seems to be skipping this loop:
for i, v in pairs(game.Players:FindFirstChild(player.Name).Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
as it seems to not print repear (repeat) OR v (Value) anyone know whats up?
Note: The thing i dont understand, is it doesnt print the value after the save, and before the save, and forgetting the for loop. I can provide extra things to.
It is ignoring the loop because when it gets to game.Players:FindFirstChild(player.Name) the return will be nil, due to that player just leaved the server. What you can try to do is iterating directly from the player object you have, you don't need to look for the object player if you already have it.
Try:
for i, v in pairs(player.Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
also it is a good practice to store data during the game and not when it leaves, all those objects are removed too when the player leaves, it is better to handle the table during the game and during player removing just update the data store.
Also a good practice is to update datastore for the player every ~5 minutes
I have a game I am coding in Tabletop Simulator where all players (P) is given a card (C). Once memorized all players put the card back into the deck (D), shuffled, and then all players are dealt one of the cards from the same deck (D). I am trying to code the simplest algorithm that prevents a player from getting their own card. Now when it comes to coding this should be simple I assume instead of creating simulations to run until it is successful.
Say you have the following:
deck, a randomized deck containing all the cards (including those the players have seen).
seen_card_id_by_player, a lookup table that give you the guid of the card a player has seen.
Then the solution is simply
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
-- Deal the specific card.
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
When we pick the card the player has already seen, it is placed back at a random location among the remaining cards. This ensures that every card has an equal chance of being drawn by the next player. This is the underlying principle of the Fisher-Yates shuffle.
Full demonstration
function broadcast_error(msg)
broadcastToAll(msg, { r=1, g=0, b=0 })
end
function get_cards_seen_by_players()
local player_ids = Player.getAvailableColors()
local error = false
local seen_card_by_player = {}
for i, player_id in ipairs(player_ids) do
local player = Player[player_id]
local hand_objs = player.getHandObjects()
local player_error = false
if #hand_objs > 1 then
player_error = true
elseif #hand_objs == 1 then
local card = hand_objs[1]
if card.tag ~= "Card" then
player_error = true
else
seen_card_by_player[player] = card
end
end
if player_error then
broadcast_error(player_id .. " doesn't have a valid hand.")
error = true
end
end
if error then
return nil
end
return seen_card_by_player
end
function run()
local deck = getObjectFromGUID("...")
local seen_card_by_player = get_cards_seen_by_players()
if seen_card_by_player == nil or next(seen_card_by_player) == nil then
return
end
local seen_card_id_by_player = {}
for player, card in pairs(seen_card_by_player) do
local card_id = card.guid
seen_card_id_by_player[player] = card_id
card.putObject(deck)
end
deck.randomize()
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
end
Create a game with a deck of cards. Place the above code in Global, replacing ... with the deck's GUID. To run the demonstration, deal one card to any number of players, then use /execute Global.call("run") in the chat window.
I am struggling to find a text comparison tool or algorithm that can compare an expected text against the current state of the text being typed.
I will have an experimentee typewrite a text that he has in front of his eyes. My idea is to compare the current state of the text against the expected text whenever something is typed. That way I want to find out when and what the subject does wrong (I also want to find errors that are not in the resulting text but were in the intermediate text for some time).
Can someone point me in a direction?
Update #1
I have access to the typing data in a csv format:
This is example output data of me typing "foOBar". Every line has the form (timestamp, Key, Press/Release)
17293398.576653,F,P
17293398.6885,F,R
17293399.135282,LeftShift,P
17293399.626881,LeftShift,R
17293401.313254,O,P
17293401.391732,O,R
17293401.827314,LeftShift,P
17293402.073046,O,P
17293402.184859,O,R
17293403.178612,B,P
17293403.301748,B,R
17293403.458137,LeftShift,R
17293404.966193,A,P
17293405.077869,A,R
17293405.725405,R,P
17293405.815159,R,R
In Python
Given your input csv file (I called it keyboard_records.csv)
17293398.576653,F,P
17293398.6885,F,R
17293399.135282,LeftShift,P
17293399.626881,LeftShift,R
17293401.313254,O,P
17293401.391732,O,R
17293401.827314,LeftShift,P
17293402.073046,O,P
17293402.184859,O,R
17293403.178612,B,P
17293403.301748,B,R
17293403.458137,LeftShift,R
17293404.966193,A,P
17293405.077869,A,R
17293405.725405,R,P
17293405.815159,R,R
The following code does the following:
Read its content and store it in a list named steps
For each step in steps recognizes what happened and
If it was a shift press or release sets a flag (shift_on) accordingly
If it was an arrow pressed moves the cursor (index of current where we insert characters) – if it the cursor is at the start or at the end of the string it shouldn't move, that's why those min() and max()
If it was a letter/number/symbol it adds it in curret at cursor position and increments cursor
Here you have it
import csv
steps = [] # list of all actions performed by user
expected = "Hello"
with open("keyboard.csv") as csvfile:
for row in csv.reader(csvfile, delimiter=','):
steps.append((float(row[0]), row[1], row[2]))
# Now we parse the information
current = [] # text written by the user
shift_on = False # is shift pressed
cursor = 0 # where is the cursor in the current text
for step in steps:
time, key, action = step
if key == 'LeftShift':
if action == 'P':
shift_on = True
else:
shift_on = False
continue
if key == 'LeftArrow' and action == 'P':
cursor = max(0, cursor-1)
continue
if key == 'RightArrow' and action == 'P':
cursor = min(len(current), cursor+1)
continue
if action == 'P':
if shift_on is True:
current.insert(cursor, key.upper())
else:
current.insert(cursor, key.lower())
cursor += 1
# Now you can join current into a string
# and compare current with expected
print(''.join(current)) # printing current (just to see what's happening)
else:
# What to do when a key is released?
# Depends on your needs...
continue
To compare current and expected have a look here.
Note: by playing around with the code above and a few more flags you can make it recognize also symbols. This will depend on your keyboard. In mine Shift + 6 = &, AltGr + E = € and Ctrl + Shift + AltGr + è = {. I think this is a good point to start.
Update
Comparing 2 texts isn't a difficult task and you can find tons of pages on the web about it.
Anyway I wanted to present you an object oriented approach to the problem, so I added the compare part that I previously omitted in the first solution.
This is still a rough code, without primary controls over the input. But, as you asked, this is pointing you in a direction.
class UserText:
# Initialize UserText:
# - empty text
# - cursor at beginning
# - shift off
def __init__(self, expected):
self.expected = expected
self.letters = []
self.cursor = 0
self.shift = False
# compares a and b and returns a
# list containing the indices of
# mismatches between a and b
def compare(a, b):
err = []
for i in range(min(len(a), len(b))):
if a[i] != b[i]:
err.append(i)
return err
# Parse a command given in the
# form (time, key, action)
def parse(self, command):
time, key, action = command
output = ""
if action == 'P':
if key == 'LeftShift':
self.shift = True
elif key == 'LeftArrow':
self.cursor = max(0, self.cursor - 1)
elif key == 'RightArrow':
self.cursor = min(len(self.letters), self.cursor + 1)
else:
# Else, a letter/number was pressed. Let's
# add it to self.letters in cursor position
if self.shift is True:
self.letters.insert(self.cursor, key.upper())
else:
self.letters.insert(self.cursor, key.lower())
self.cursor += 1
########## COMPARE WITH EXPECTED ##########
output += "Expected: \t" + self.expected + "\n"
output += "Current: \t" + str(self) + "\n"
errors = UserText.compare(str(self), self.expected[:len(str(self))])
output += "\t\t"
i = 0
for e in errors:
while i != e:
output += " "
i += 1
output += "^"
i += 1
output += "\n[{} errors at time {}]".format(len(errors), time)
return output
else:
if key == 'LeftShift':
self.shift = False
return output
def __str__(self):
return "".join(self.letters)
import csv
steps = [] # list of all actions performed by user
expected = "foobar"
with open("keyboard.csv") as csvfile:
for row in csv.reader(csvfile, delimiter=','):
steps.append((float(row[0]), row[1], row[2]))
# Now we parse the information
ut = UserText(expected)
for step in steps:
print(ut.parse(step))
The output for the csv file above was:
Expected: foobar
Current: f
[0 errors at time 17293398.576653]
Expected: foobar
Current: fo
[0 errors at time 17293401.313254]
Expected: foobar
Current: foO
^
[1 errors at time 17293402.073046]
Expected: foobar
Current: foOB
^^
[2 errors at time 17293403.178612]
Expected: foobar
Current: foOBa
^^
[2 errors at time 17293404.966193]
Expected: foobar
Current: foOBar
^^
[2 errors at time 17293405.725405]
I found the solution to my own question around a year ago. Now i have time to share it with you:
In their 2003 paper 'Metrics for text entry research: An evaluation of MSD and KSPC, and a new unified error metric', R. William Soukoreff and I. Scott MacKenzie propose three major new metrics: 'total error rate', 'corrected error rate' and 'not corrected error rate'. These metrics have become well established since the publication of this paper. These are exaclty the metrics i was looking for.
If you are trying to do something similiar to what i did, e.g. compare the writing performance on different input devices this is the way to go.
I am fairly new to coding, and am currently learning my first language (python) using the book "Learn Python the Hard Way" but this is not a specific exercise in the book and I am just practicing while I am reading code for Exercise 23 and am currently am just trying to figure out if this is even possible...
My first file is pr1.py:
def func():
a = float(raw_input("Enter Your Age:"))
b = float(raw_input("Enter Your Weight:"))
c = float(raw_input("Enter Your Height:"))
age = "a"
weight = "b"
height = "c"
if __name__ == "__main__":
print("This is pr1.py")
else:
print("%s is being imported to another file") % __name__
My second file is pr2.py
import pr1
def func():
x = raw_input("Enter Your Race:")
y = raw_input("Enter Your Gender:")
z = raw_input("Enter Your Language:")
print "Lets find your numbers"
pr1.func()
print "Lets find your identity"
func()
race = "x"
gender = "y"
language = "z"
if __name__ == "__main__":
print("This is pr2.py")
else:
print("%s is being imported into another file") % __name__
This is my 3rd file pr3.py
import pr1
print "%s = a %s = b %s = c" % (age, weight, height)
import pr2
print "%s = x, %s = y, %s = z" % (race, gender, language)
When I run pr3.py and comment out the scripts to "print" line 3 and line 7 this is what i get:
python pr3.py
pr1 is being imported to another file
Lets find your numbers
Enter Your Age:25
Enter Your Weight:224
Enter Your Height:76
Lets find your identity
Enter Your Race:white
Enter Your Gender:male
Enter Your Language:english
pr2 is being imported into another file
and I am expecting the pr3.py file to print those statement's with the previously defined variable's.
but instead it comes up with this error:
pr1 is being imported to another file
Traceback (most recent call last):
File "pr3.py", line 3, in <module>
print "%s = a %s = b %s = c" % (age, weight, height)
NameError: name 'age' is not defined
Now when I run my last file in the command, I am expecting it to import the previous 2 files, so I can input the data I put into raw_input, and then use use it in other files... but it seems like once both files get imported and I input the data into their respective raw_input's, it seems as if the pr3.py forget's the raw input and their corresponding variable's.
Please forgive me if I am totally lacking some obvious knowledge that could fix all this, but I am very new to coding and not even a month ago, I didn't even know you could create a directory in the terminal.
Thank's for reading and I would appreciate any help.
Okey, here are a couple of things.
First I will say which obvious things are wrong with your code.
After that I will show you an example of your code, using classes.
So, first:
age, weight, height are all defined in pr1.py, so eiter you need to refer to them as pr1.age, pr1.weight, pr1.height, or you from pr1 import age, weight, height. Same applies for race, gender, language in pr2.py
That said, you might expect to get what you inputted to be printed out. But you only assigned the characters 'a', 'b', 'c', 'x', 'y' and 'z' to those variables.
Also you print age, weight and height before you even run func() in pr2.py
So second: how do we fix this. First you need to think about in which order things are happening, when you do imports. Also you need to think about, if the variables you refer to, really are set anywhere.
In this case you set your raw_input's to variables insde a function, and they will only be accessible inside that function.
This can be fixed by using globals, or by making an object. I will reccommend using object (classes).
Since you say you are fairly new to programming, classes might seem over your head now, but when you get it, it solves alot of these problems.
Also you will get to classes soon enough in Learn Python The Hard Way soon enough.
To take your code as example:
pr1.py:
class Numbers:
def func(self):
self.age = float(raw_input("Enter Your Age:"))
self.weight = float(raw_input("Enter Your Weight:"))
self.height = float(raw_input("Enter Your Height:"))
if __name__ == "__main__":
print("This is pr1.py")
else:
print("%s is being imported to another file") % __name__
pr2.py:
from pr1 import Numbers
class Identity:
def func(self):
self.race = raw_input("Enter Your Race:")
self.gender = raw_input("Enter Your Gender:")
self.language = raw_input("Enter Your Language:")
print "Lets find your numbers"
nrs = Numbers()
nrs.func()
print "Lets find your identity"
ids = Identity()
ids.func()
if __name__ == "__main__":
print("This is pr2.py")
else:
print("%s is being imported into another file") % __name__
pr3.py:
from pr2 import *
print "%s = a %s = b %s = c" % (nrs.age, nrs.weight, nrs.height)
print "%s = x, %s = y, %s = z" % (ids.race, ids.gender, ids.language)
I am trying to extract information from a large file and cannot figure out how to extract strings from file lines only when a previous line in the same record within the file has been matched by regex. An example of one record in the file is as follows:
*NEW RECORD
RECTYPE = D
MH = Informed Consent
AQ = ES HI LJ PX SN ST
ENTRY = Consent, Informed
MN = N03.706.437.650.312
MN = N03.706.535.489
FX = Disclosure
FX = Mental Competency
FX = Therapeutic Misconception
FX = Treatment Refusal
ST = T058
ST = T078
AN = competency to consent: coordinate IM with MENTAL COMPETENCY (IM)
PI = Jurisprudence (1966-1970)
PI = Physician-Patient Relations (1966-1970)
MS = Voluntary authorization, by a patient or research subject, etc,...
This file contains over 20,000 records like this example. I want to identify a small percent of those records using the "MH" field. In this example, I want to find "Informed Consent", and then use regex to extract the information in the FX, AN, and MS fields only within that record. So far, I have opened the file, accessed the hash that the MH terms are stored in, and been able to extract those terms from the records in the file. I also have a functioning regex that identifies the content in the "FX" field.
File.open('mesh_descriptor.bin').each do |file_line|
file_line = file_line.chomp
# read each key of candidate_descriptor_keys
candidate_descriptor_keys.each do |cand_term|
if file_line =~ /^MH\s=\s(#{cand_term})$/
mesh_header = $1
puts "MH from Mesh Descriptor file is: #{mesh_header}"
if file_line =~ /^FX\s=\s(.*)$/
see_also = $1
puts " See_Also from Descriptor file is: #{see_also}"
end
end
end
end
The hash contains the following MH (keys):
candidate_descriptor_keys = ["Body Weight", "Obesity", "Thinness", "Fetal Weight", "Overweight"]
I had success extracting "FX" when I put the statement outside of the "if" statement to extract "MH", but all of the "FX" from the whole file were retrieved - not what I need. I thought putting the "if" statement for "FX" within the previous "if" statement would restrict the results to only those found when the first statement is true, but I am getting no results (also no errors) with this strategy. What I would like as a result is:
> Informed Consent
> Disclosure
> Mental Competency
> Therapeutic Misconception
> Treatment Refusal
as well as the strings within the "AN" and "MS" fields for only those records matching "MH". Any suggestions would be helpful!
I think this may be what you are looking for, but if not, let me know and I will change it. Look especially at the very end to see if that is the sort of output (for input having two records, both with a "MH" field) you want. I will also add a "explanation" section at the end once I have understood your question correctly.
I have assumed that each record begins
*NEW_RECORD
and you wish to identify all lines beginning "MH" whose field is one of the elements of:
candidate_descriptor_keys =
["Body Weight", "Obesity", "Thinness", "Informed Consent"]
and for each match, you would like to print the contents of the lines for the same record that begin with "FX", "AN" and "MS".
Code
NEW_RECORD_MARKER = "*NEW RECORD"
def getem(fname, candidate_descriptor_keys)
line = 0
found_mh = false
File.open(fname).each do |file_line|
file_line = file_line.strip
case
when file_line == NEW_RECORD_MARKER
puts # space between records
found_mh = false
when found_mh == false
candidate_descriptor_keys.each do |cand_term|
if file_line =~ /^MH\s=\s(#{cand_term})$/
found_mh = true
puts "MH from line #{line} of file is: #{cand_term}"
break
end
end
when found_mh
["FX", "AN", "MS"].each do |des|
if file_line =~ /^#{des}\s=\s(.*)$/
see_also = $1
puts " Line #{line} of file is: #{des}: #{see_also}"
end
end
end
line += 1
end
end
Example
Let's begin be creating a file, starging with a "here document that contains two records":
records =<<_
*NEW RECORD
RECTYPE = D
MH = Informed Consent
AQ = ES HI LJ PX SN ST
ENTRY = Consent, Informed
MN = N03.706.437.650.312
MN = N03.706.535.489
FX = Disclosure
FX = Mental Competency
FX = Therapeutic Misconception
FX = Treatment Refusal
ST = T058
ST = T078
AN = competency to consent
PI = Jurisprudence (1966-1970)
PI = Physician-Patient Relations (1966-1970)
MS = Voluntary authorization
*NEW RECORD
MH = Obesity
AQ = ES HI LJ PX SN ST
ENTRY = Obesity
MN = N03.706.437.650.312
MN = N03.706.535.489
FX = 1st FX
FX = 2nd FX
AN = Only AN
PI = Jurisprudence (1966-1970)
PI = Physician-Patient Relations (1966-1970)
MS = Only MS
_
If you puts records you will see it is just a string. (You'll see that I shortened two of them.) Now write it to a file:
File.write('mesh_descriptor', records)
If you wish to confirm the file contents, you could do this:
puts File.read('mesh_descriptor')
We also need to define define the array candidate_descriptor_keys:
candidate_descriptor_keys =
["Body Weight", "Obesity", "Thinness", "Informed Consent"]
We can now execute the method getem:
getem('mesh_descriptor', candidate_descriptor_keys)
MH from line 2 of file is: Informed Consent
Line 7 of file is: FX: Disclosure
Line 8 of file is: FX: Mental Competency
Line 9 of file is: FX: Therapeutic Misconception
Line 10 of file is: FX: Treatment Refusal
Line 13 of file is: AN: competency to consent
Line 16 of file is: MS: Voluntary authorization
MH from line 18 of file is: Obesity
Line 23 of file is: FX: 1st FX
Line 24 of file is: FX: 2nd FX
Line 25 of file is: AN: Only AN
Line 28 of file is: MS: Only MS